From e9d81c2826423fd91287fa13bf593a544b6a2452 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 3 Feb 2022 09:42:48 -0600 Subject: [PATCH 1/5] Add mdns module This allows for CircuitPython to resolve a .local domain and find other devices with MDNS services. First step for #6174 --- locale/circuitpython.pot | 13 ++ ports/espressif/CMakeLists.txt | 2 +- ports/espressif/Makefile | 2 +- .../espressif_esp32s2_devkitc_1_n4/board.c | 48 ++++ .../mpconfigboard.h | 39 ++++ .../mpconfigboard.mk | 17 ++ .../espressif_esp32s2_devkitc_1_n4/pins.c | 53 +++++ .../espressif_esp32s2_devkitc_1_n4/sdkconfig | 5 + .../mpconfigboard.mk | 4 +- .../espressif/common-hal/mdns/RemoteService.c | 52 +++++ .../espressif/common-hal/mdns/RemoteService.h | 34 +++ ports/espressif/common-hal/mdns/Server.c | 149 ++++++++++++ ports/espressif/common-hal/mdns/Server.h | 37 +++ ports/espressif/common-hal/mdns/__init__.c | 1 + ports/espressif/common-hal/wifi/Radio.c | 7 + py/circuitpy_defns.mk | 6 + py/circuitpy_mpconfig.mk | 3 + shared-bindings/mdns/RemoteService.c | 157 +++++++++++++ shared-bindings/mdns/RemoteService.h | 41 ++++ shared-bindings/mdns/Server.c | 214 ++++++++++++++++++ shared-bindings/mdns/Server.h | 43 ++++ shared-bindings/mdns/__init__.c | 56 +++++ shared-bindings/mdns/__init__.h | 27 +++ tools/ci_check_duplicate_usb_vid_pid.py | 1 + 24 files changed, 1007 insertions(+), 4 deletions(-) create mode 100644 ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/board.c create mode 100644 ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.h create mode 100644 ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.mk create mode 100644 ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/pins.c create mode 100644 ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/sdkconfig create mode 100644 ports/espressif/common-hal/mdns/RemoteService.c create mode 100644 ports/espressif/common-hal/mdns/RemoteService.h create mode 100644 ports/espressif/common-hal/mdns/Server.c create mode 100644 ports/espressif/common-hal/mdns/Server.h create mode 100644 ports/espressif/common-hal/mdns/__init__.c create mode 100644 shared-bindings/mdns/RemoteService.c create mode 100644 shared-bindings/mdns/RemoteService.h create mode 100644 shared-bindings/mdns/Server.c create mode 100644 shared-bindings/mdns/Server.h create mode 100644 shared-bindings/mdns/__init__.c create mode 100644 shared-bindings/mdns/__init__.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index fca18d79f7..0ce564f1f7 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -2408,6 +2408,10 @@ msgstr "" msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/mdns/Server.c +msgid "Unable to start mDNS query" +msgstr "" + #: shared-bindings/nvm/ByteArray.c msgid "Unable to write to nvm." msgstr "" @@ -3625,6 +3629,14 @@ msgstr "" msgid "loopback + silent mode not supported by peripheral" msgstr "" +#: ports/espressif/common-hal/mdns/Server.c +msgid "mDNS already initialized" +msgstr "" + +#: ports/espressif/common-hal/mdns/Server.c +msgid "mDNS only works with built-in WiFi" +msgstr "" + #: py/parse.c msgid "malformed f-string" msgstr "" @@ -4072,6 +4084,7 @@ msgstr "" #: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h #: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h #: ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/mpconfigboard.h +#: ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.h #: ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/mpconfigboard.h #: ports/espressif/boards/espressif_esp32s3_box/mpconfigboard.h #: ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/mpconfigboard.h diff --git a/ports/espressif/CMakeLists.txt b/ports/espressif/CMakeLists.txt index afbb51bbad..4c834397b9 100644 --- a/ports/espressif/CMakeLists.txt +++ b/ports/espressif/CMakeLists.txt @@ -6,7 +6,7 @@ set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf) # The component list here determines what options we get in menuconfig and what the ninja file # can build. -set(COMPONENTS esptool_py soc driver log main esp-tls mbedtls esp_event esp_adc_cal esp_netif esp_wifi lwip wpa_supplicant freertos bt) +set(COMPONENTS esptool_py soc driver log main esp-tls mbedtls mdns esp_event esp_adc_cal esp_netif esp_wifi lwip wpa_supplicant freertos bt) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(circuitpython) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index beb0ccd679..070708ca60 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -360,7 +360,7 @@ $(HEADER_BUILD)/qstr.split: | $(BUILD)/esp-idf/config/sdkconfig.h BINARY_WIFI_BLOBS = libcoexist.a libcore.a libespnow.a libmesh.a libnet80211.a libpp.a libsmartconfig.a libwapi.a BINARY_BLOBS = esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libphy.a $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, $(BINARY_WIFI_BLOBS)) -ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) app_update bootloader_support driver efuse esp_adc_cal esp_common esp_event esp_hw_support esp_ipc esp_netif esp_pm esp_phy esp_ringbuf esp_rom esp_system esp_timer esp-tls esp_wifi freertos hal heap log lwip mbedtls newlib nvs_flash pthread soc spi_flash vfs wpa_supplicant +ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) app_update bootloader_support driver efuse esp_adc_cal esp_common esp_event esp_hw_support esp_ipc esp_netif esp_pm esp_phy esp_ringbuf esp_rom esp_system esp_timer esp-tls esp_wifi freertos hal heap log lwip mbedtls mdns newlib nvs_flash pthread soc spi_flash vfs wpa_supplicant ifneq ($(CIRCUITPY_BLEIO),0) ESP_IDF_COMPONENTS_LINK += bt BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libbtbb.a \ diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/board.c b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/board.c new file mode 100644 index 0000000000..0432485111 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/board.c @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * 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 "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" + +void board_init(void) { + // Debug UART + #ifdef DEBUG + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); + #endif /* DEBUG */ +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} + +void board_deinit(void) { +} diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.h b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.h new file mode 100644 index 0000000000..45f68f92be --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * 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. + */ + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "ESP32-S2-DevKitC-1-N4" +#define MICROPY_HW_MCU_NAME "ESP32S2" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO18) + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +#define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n") diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.mk new file mode 100644 index 0000000000..e902c3975a --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.mk @@ -0,0 +1,17 @@ +USB_VID = 0x303A +USB_PID = 0x7009 +USB_PRODUCT = "ESP32-S2-DevKitC-1-N4" +USB_MANUFACTURER = "Espressif" + +IDF_TARGET = esp32s2 + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +# The default queue depth of 16 overflows on release builds, +# so increase it to 32. +CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32 + +CIRCUITPY_ESP_FLASH_MODE=dio +CIRCUITPY_ESP_FLASH_FREQ=40m +CIRCUITPY_ESP_FLASH_SIZE=4MB diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/pins.c b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/pins.c new file mode 100644 index 0000000000..435f251c80 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/pins.c @@ -0,0 +1,53 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/sdkconfig b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/sdkconfig new file mode 100644 index 0000000000..1aad0eadd1 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/sdkconfig @@ -0,0 +1,5 @@ +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s2" +# end of LWIP diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/mpconfigboard.mk index 7644ce232c..d007558640 100644 --- a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/mpconfigboard.mk @@ -1,5 +1,5 @@ -USB_VID = 0x239A -USB_PID = 0x80A6 +USB_VID = 0x303A +USB_PID = 0x7009 USB_PRODUCT = "ESP32-S2-DevKitC-1-N4R2" USB_MANUFACTURER = "Espressif" diff --git a/ports/espressif/common-hal/mdns/RemoteService.c b/ports/espressif/common-hal/mdns/RemoteService.c new file mode 100644 index 0000000000..69c96fe0f8 --- /dev/null +++ b/ports/espressif/common-hal/mdns/RemoteService.c @@ -0,0 +1,52 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * 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 "shared-bindings/mdns/RemoteService.h" + +const char * common_hal_mdns_remoteservice_get_service_type(mdns_remoteservice_obj_t *self) { + return self->result->service_type; +} + +const char * common_hal_mdns_remoteservice_get_protocol(mdns_remoteservice_obj_t *self) { + return self->result->proto; +} + +const char * common_hal_mdns_remoteservice_get_instance_name(mdns_remoteservice_obj_t *self) { + return self->result->instance_name; +} + +const char * common_hal_mdns_remoteservice_get_hostname(mdns_remoteservice_obj_t *self) { + return self->result->hostname; +} + +mp_int_t common_hal_mdns_remoteservice_get_port(mdns_remoteservice_obj_t *self) { + return self->result->port; +} + +void common_hal_mdns_remoteservice_deinit(mdns_remoteservice_obj_t *self) { + mdns_query_results_free(self->result); + self->result = NULL; +} diff --git a/ports/espressif/common-hal/mdns/RemoteService.h b/ports/espressif/common-hal/mdns/RemoteService.h new file mode 100644 index 0000000000..ca59f5ece6 --- /dev/null +++ b/ports/espressif/common-hal/mdns/RemoteService.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * 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. + */ + +#pragma once + +#include "components/mdns/include/mdns.h" + +typedef struct { + mp_obj_base_t base; + mdns_result_t *result; +} mdns_remoteservice_obj_t; diff --git a/ports/espressif/common-hal/mdns/Server.c b/ports/espressif/common-hal/mdns/Server.c new file mode 100644 index 0000000000..eecd1ad66e --- /dev/null +++ b/ports/espressif/common-hal/mdns/Server.c @@ -0,0 +1,149 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * 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 "shared-bindings/mdns/Server.h" + +#include "py/gc.h" +#include "py/runtime.h" +#include "shared-bindings/mdns/RemoteService.h" +#include "shared-bindings/wifi/__init__.h" + +#include "components/mdns/include/mdns.h" + +STATIC bool inited = false; + +void common_hal_mdns_server_construct(mdns_server_obj_t *self, mp_obj_t network_interface) { + if (network_interface != MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj)) { + mp_raise_ValueError(translate("mDNS only works with built-in WiFi")); + return; + } + if (inited) { + mp_raise_RuntimeError(translate("mDNS already initialized")); + } + mdns_init(); + + uint8_t mac[6]; + esp_netif_get_mac(common_hal_wifi_radio_obj.netif, mac); + snprintf(self->default_hostname, sizeof(self->default_hostname), "cpy-%02x%02x%02x", mac[3], mac[4], mac[5]); + common_hal_mdns_server_set_hostname(self, self->default_hostname); + + // Set a delegated entry to ourselves. This allows us to respond to "circuitpython.local" + // queries as well. + // TODO: Allow for disabling this with `supervisor.disable_web_workflow()`. + mdns_ip_addr_t our_ip; + esp_netif_get_ip_info(common_hal_wifi_radio_obj.netif, &common_hal_wifi_radio_obj.ip_info); + our_ip.next = NULL; + our_ip.addr.type = ESP_IPADDR_TYPE_V4; + our_ip.addr.u_addr.ip4 = common_hal_wifi_radio_obj.ip_info.ip; + our_ip.addr.u_addr.ip6.addr[1] = 0; + our_ip.addr.u_addr.ip6.addr[2] = 0; + our_ip.addr.u_addr.ip6.addr[3] = 0; + our_ip.addr.u_addr.ip6.zone = 0; + mdns_delegate_hostname_add("circuitpython", &our_ip); +} + +void common_hal_mdns_server_deinit(mdns_server_obj_t *self) { + inited = false; + mdns_free(); +} + +bool common_hal_mdns_server_deinited(mdns_server_obj_t *self) { + // This returns INVALID_STATE when not initialized and INVALID_PARAM when it + // is. + return mdns_instance_name_set(NULL) == ESP_ERR_INVALID_STATE; +} + +const char * common_hal_mdns_server_get_hostname(mdns_server_obj_t *self) { + return self->hostname; +} + +void common_hal_mdns_server_set_hostname(mdns_server_obj_t *self, const char *hostname) { + mdns_hostname_set(hostname); + self->hostname = hostname; +} + +const char * common_hal_mdns_server_get_instance_name(mdns_server_obj_t *self) { + if (self->instance_name == NULL) { + return self->hostname; + } + return self->instance_name; +} + +void common_hal_mdns_server_set_instance_name(mdns_server_obj_t *self, const char *instance_name) { + mdns_instance_name_set(instance_name); + self->instance_name = instance_name; +} + +mp_obj_t common_hal_mdns_server_find(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_float_t timeout) { + mdns_search_once_t *search = mdns_query_async_new(NULL, service_type, protocol, MDNS_TYPE_PTR, timeout * 1000, 255, NULL); + if (search == NULL) { + mp_raise_RuntimeError(translate("Unable to start mDNS query")); + } + mdns_result_t *results; + while (!mdns_query_async_get_results(search, 1, &results)) { + RUN_BACKGROUND_TASKS; + } + mdns_query_async_delete(search); + // Count how many results we got. + // TODO: Remove this loop when moving off 4.4. Newer APIs will give us num_results + // back directly. + mdns_result_t *next = results; + uint8_t num_results = 0; + while (next != NULL) { + num_results++; + next = next->next; + } + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_results, NULL)); + next = results; + // Don't error if we're out of memory. Instead, truncate the tuple. + uint8_t added = 0; + while (next != NULL) { + mdns_remoteservice_obj_t *service = gc_alloc(sizeof(mdns_remoteservice_obj_t), true, false); + if (service == NULL) { + if (added == 0) { + m_malloc_fail(sizeof(mdns_remoteservice_obj_t)); + } + // Free the remaining results from the IDF because we don't have + // enough space in Python. + mdns_query_results_free(next); + break; + } + service->result = next; + service->base.type = &mdns_remoteservice_type; + next = next->next; + // Break the linked list so we free each result separately. + service->result->next = NULL; + tuple->items[added] = MP_OBJ_FROM_PTR(service); + added++; + } + tuple->len = added; + + return MP_OBJ_FROM_PTR(tuple); +} + +void common_hal_mdns_server_advertise_service(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_int_t port) { + mdns_service_add(NULL, service_type, protocol, port, NULL, 0); +} diff --git a/ports/espressif/common-hal/mdns/Server.h b/ports/espressif/common-hal/mdns/Server.h new file mode 100644 index 0000000000..770f55ece4 --- /dev/null +++ b/ports/espressif/common-hal/mdns/Server.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * 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. + */ + +#pragma once + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + const char *hostname; + const char *instance_name; + // "cpy-" "XXXXXX" "\0" + char default_hostname[4 + 6 + 1]; +} mdns_server_obj_t; diff --git a/ports/espressif/common-hal/mdns/__init__.c b/ports/espressif/common-hal/mdns/__init__.c new file mode 100644 index 0000000000..57740777c8 --- /dev/null +++ b/ports/espressif/common-hal/mdns/__init__.c @@ -0,0 +1 @@ +// No mdns module functions. diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index 5d4fcab417..4f92425c87 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -42,6 +42,10 @@ #include "components/esp_wifi/include/esp_wifi.h" #include "components/lwip/include/apps/ping/ping_sock.h" +#if CIRCUITPY_MDNS +#include "components/mdns/include/mdns.h" +#endif + #define MAC_ADDRESS_LENGTH 6 static void set_mode_station(wifi_radio_obj_t *self, bool state) { @@ -91,6 +95,9 @@ void common_hal_wifi_radio_set_enabled(wifi_radio_obj_t *self, bool enabled) { if (self->current_scan != NULL) { common_hal_wifi_radio_stop_scanning_networks(self); } + #if CIRCUITPY_MDNS + mdns_free(); + #endif ESP_ERROR_CHECK(esp_wifi_stop()); self->started = false; return; diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index e7cbacf0a2..550396f2ba 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -214,6 +214,9 @@ endif ifeq ($(CIRCUITPY_MICROCONTROLLER),1) SRC_PATTERNS += microcontroller/% endif +ifeq ($(CIRCUITPY_MDNS),1) +SRC_PATTERNS += mdns/% +endif ifeq ($(CIRCUITPY_NEOPIXEL_WRITE),1) SRC_PATTERNS += neopixel_write/% endif @@ -401,6 +404,9 @@ SRC_COMMON_HAL_ALL = \ microcontroller/Pin.c \ microcontroller/Processor.c \ microcontroller/__init__.c \ + mdns/__init__.c \ + mdns/Server.c \ + mdns/RemoteService.c \ neopixel_write/__init__.c \ nvm/ByteArray.c \ nvm/__init__.c \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 9de701133a..87fcc8ff60 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -263,6 +263,9 @@ CFLAGS += -DCIRCUITPY_MEMORYMONITOR=$(CIRCUITPY_MEMORYMONITOR) CIRCUITPY_MICROCONTROLLER ?= 1 CFLAGS += -DCIRCUITPY_MICROCONTROLLER=$(CIRCUITPY_MICROCONTROLLER) +CIRCUITPY_MDNS ?= $(CIRCUITPY_WIFI) +CFLAGS += -DCIRCUITPY_MDNS=$(CIRCUITPY_MDNS) + CIRCUITPY_MSGPACK ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_MSGPACK=$(CIRCUITPY_MSGPACK) diff --git a/shared-bindings/mdns/RemoteService.c b/shared-bindings/mdns/RemoteService.c new file mode 100644 index 0000000000..4e1c63099d --- /dev/null +++ b/shared-bindings/mdns/RemoteService.c @@ -0,0 +1,157 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2017 Glenn Ruben Bakke + * + * 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 "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/mdns/RemoteService.h" + +//| class RemoteService: +//| """Encapsulates information about a remote service that was found during a query. This +//| object may only be created by a `mdns.Server`. It has no user-visible constructor.""" +//| + +//| def __init__(self) -> None: +//| """Cannot be instantiated directly. Use `mdns.Server.query`.""" +//| ... +//| + +//| hostname: str +//| """The hostname of the device (read-only),.""" +//| +STATIC mp_obj_t mdns_remoteservice_get_hostname(mp_obj_t self_in) { + mdns_remoteservice_obj_t *self = MP_OBJ_TO_PTR(self_in); + const char *hostname = common_hal_mdns_remoteservice_get_hostname(self); + return mp_obj_new_str(hostname, strlen(hostname)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mdns_remoteservice_get_hostname_obj, mdns_remoteservice_get_hostname); + +const mp_obj_property_t mdns_remoteservice_hostname_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&mdns_remoteservice_get_hostname_obj, + MP_ROM_NONE, + MP_ROM_NONE }, +}; + +//| instance_name: str +//| """The human readable instance name for the service. (read-only)""" +//| +STATIC mp_obj_t remoteservice_get_instance_name(mp_obj_t self_in) { + mdns_remoteservice_obj_t *self = MP_OBJ_TO_PTR(self_in); + const char *instance_name = common_hal_mdns_remoteservice_get_instance_name(self); + return mp_obj_new_str(instance_name, strlen(instance_name)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mdns_remoteservice_get_instance_name_obj, remoteservice_get_instance_name); + +const mp_obj_property_t mdns_remoteservice_instance_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&mdns_remoteservice_get_instance_name_obj, + MP_ROM_NONE, + MP_ROM_NONE }, +}; + +//| service_type: str +//| """The service type string such as ``_http``. (read-only)""" +//| +STATIC mp_obj_t remoteservice_get_service_type(mp_obj_t self_in) { + mdns_remoteservice_obj_t *self = MP_OBJ_TO_PTR(self_in); + const char *service_type = common_hal_mdns_remoteservice_get_service_type(self); + return mp_obj_new_str(service_type, strlen(service_type)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mdns_remoteservice_get_service_type_obj, remoteservice_get_service_type); + +const mp_obj_property_t mdns_remoteservice_service_type_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&mdns_remoteservice_get_service_type_obj, + MP_ROM_NONE, + MP_ROM_NONE }, +}; + +//| protocol: str +//| """The protocol string such as ``_tcp``. (read-only)""" +//| +STATIC mp_obj_t remoteservice_get_protocol(mp_obj_t self_in) { + mdns_remoteservice_obj_t *self = MP_OBJ_TO_PTR(self_in); + const char *protocol = common_hal_mdns_remoteservice_get_protocol(self); + return mp_obj_new_str(protocol, strlen(protocol)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mdns_remoteservice_get_protocol_obj, remoteservice_get_protocol); + +const mp_obj_property_t mdns_remoteservice_protocol_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&mdns_remoteservice_get_protocol_obj, + MP_ROM_NONE, + MP_ROM_NONE }, +}; + +//| port: int +//| """Port number used for the service. (read-only)""" +//| +STATIC mp_obj_t remoteservice_get_port(mp_obj_t self_in) { + mdns_remoteservice_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_mdns_remoteservice_get_port(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mdns_remoteservice_get_port_obj, remoteservice_get_port); + +const mp_obj_property_t mdns_remoteservice_port_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&mdns_remoteservice_get_port_obj, + MP_ROM_NONE, + MP_ROM_NONE }, +}; + +//| def __del__(self) -> None: +//| """Deletes the RemoteService object.""" +//| ... +//| +STATIC mp_obj_t mdns_remoteservice_obj_deinit(mp_obj_t self_in) { + mdns_remoteservice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_mdns_remoteservice_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mdns_remoteservice_deinit_obj, mdns_remoteservice_obj_deinit); + +STATIC const mp_rom_map_elem_t mdns_remoteservice_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mdns_remoteservice_hostname_obj) }, + { MP_ROM_QSTR(MP_QSTR_instance_name), MP_ROM_PTR(&mdns_remoteservice_instance_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&mdns_remoteservice_instance_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_service_type), MP_ROM_PTR(&mdns_remoteservice_service_type_obj) }, + { MP_ROM_QSTR(MP_QSTR_protocol), MP_ROM_PTR(&mdns_remoteservice_protocol_obj) }, + { MP_ROM_QSTR(MP_QSTR_port), MP_ROM_PTR(&mdns_remoteservice_port_obj) }, + + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mdns_remoteservice_deinit_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mdns_remoteservice_locals_dict, mdns_remoteservice_locals_dict_table); + +const mp_obj_type_t mdns_remoteservice_type = { + { &mp_type_type }, + .name = MP_QSTR_RemoteService, + .locals_dict = (mp_obj_dict_t *)&mdns_remoteservice_locals_dict +}; diff --git a/shared-bindings/mdns/RemoteService.h b/shared-bindings/mdns/RemoteService.h new file mode 100644 index 0000000000..055ea24d2c --- /dev/null +++ b/shared-bindings/mdns/RemoteService.h @@ -0,0 +1,41 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2017 Glenn Ruben Bakke + * + * 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. + */ + +#pragma once + +#include "py/obj.h" +#include "common-hal/mdns/RemoteService.h" + +extern const mp_obj_type_t mdns_remoteservice_type; + +const char * common_hal_mdns_remoteservice_get_service_type(mdns_remoteservice_obj_t *self); +const char * common_hal_mdns_remoteservice_get_protocol(mdns_remoteservice_obj_t *self); +const char * common_hal_mdns_remoteservice_get_instance_name(mdns_remoteservice_obj_t *self); +const char * common_hal_mdns_remoteservice_get_hostname(mdns_remoteservice_obj_t *self); +mp_int_t common_hal_mdns_remoteservice_get_port(mdns_remoteservice_obj_t *self); +void common_hal_mdns_remoteservice_deinit(mdns_remoteservice_obj_t *self); diff --git a/shared-bindings/mdns/Server.c b/shared-bindings/mdns/Server.c new file mode 100644 index 0000000000..7ffc67f4d9 --- /dev/null +++ b/shared-bindings/mdns/Server.c @@ -0,0 +1,214 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * 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 "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/mdns/__init__.h" +#include "shared-bindings/mdns/Server.h" +#include "shared-bindings/util.h" + +//| class Server: +//| """The MDNS Server responds to queries for this device's information and allows for querying +//| other devices.""" +//| + +//| def __init__(self, network_interface: wifi.Radio) -> None: +//| """ +//| Constructs or returns the mdns.Server for the given network_interface. (CircuitPython +//| may already be using it.) Only native interfaces are currently supported. +//| """ +//| ... +//| +STATIC mp_obj_t mdns_server_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_network_interface }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_network_interface, MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mdns_server_obj_t *self = m_new_obj(mdns_server_obj_t); + self->base.type = &mdns_server_type; + common_hal_mdns_server_construct(self, args[ARG_network_interface].u_obj); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Stops the server""" +//| ... +//| +STATIC mp_obj_t mdns_server_obj_deinit(mp_obj_t self_in) { + mdns_server_obj_t *self = (mdns_server_obj_t *)self_in; + common_hal_mdns_server_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mdns_server_deinit_obj, mdns_server_obj_deinit); + +STATIC void check_for_deinit(mdns_server_obj_t *self) { + if (common_hal_mdns_server_deinited(self)) { + raise_deinited_error(); + } +} + +//| +//| hostname: str +//| """Hostname resolvable as ``.local`` in addition to ``circuitpython.local``. Make +//| sure this is unique across all devices on the network. It defaults to ``cpy-######`` +//| where ``######`` is the hex digits of the last three bytes of the mac address.""" +//| +STATIC mp_obj_t mdns_server_get_hostname(mp_obj_t self) { + check_for_deinit(self); + const char *hostname = common_hal_mdns_server_get_hostname(self); + return mp_obj_new_str(hostname, strlen(hostname)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mdns_server_get_hostname_obj, mdns_server_get_hostname); + +static mp_obj_t mdns_server_set_hostname(mp_obj_t self, mp_obj_t hostname) { + check_for_deinit(self); + common_hal_mdns_server_set_hostname(self, mp_obj_str_get_str(hostname)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mdns_server_set_hostname_obj, mdns_server_set_hostname); + +const mp_obj_property_t mdns_server_hostname_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&mdns_server_get_hostname_obj, + (mp_obj_t)&mdns_server_set_hostname_obj, + MP_ROM_NONE }, +}; + +//| instance_name: str +//| """Human readable name to describe the device.""" +//| +STATIC mp_obj_t mdns_server_get_instance_name(mp_obj_t self) { + check_for_deinit(self); + const char *instance_name = common_hal_mdns_server_get_instance_name(self); + return mp_obj_new_str(instance_name, strlen(instance_name)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mdns_server_get_instance_name_obj, mdns_server_get_instance_name); + +STATIC mp_obj_t mdns_server_set_instance_name(mp_obj_t self, mp_obj_t new_instance_name) { + check_for_deinit(self); + common_hal_mdns_server_set_instance_name(self, mp_obj_str_get_str(new_instance_name)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(mdns_server_set_instance_name_obj, mdns_server_set_instance_name); + +const mp_obj_property_t mdns_server_instance_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&mdns_server_get_instance_name_obj, + (mp_obj_t)&mdns_server_set_instance_name_obj, + MP_ROM_NONE }, +}; + + +//| def find(self, service_type: str, protocol: str, *, timeout: float = 1) -> Tuple[RemoteService]: +//| """Find all locally available remote services with the given service type and protocol. +//| +//| This doesn't allow for direct hostname lookup. To do that, use +//| `socketpool.SocketPool.getaddrinfo()` +//| +//| :param str service_type: The service type such as "_http" +//| :param str protocol: The service protocol such as "_tcp" +//| :param float/int timeout: Time to wait for responses""" +//| ... +//| +STATIC mp_obj_t mdns_server_find(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mdns_server_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + + enum { ARG_service_type, ARG_protocol, ARG_timeout }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_service_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(1)} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + const char *service_type = mp_obj_str_get_str(args[ARG_service_type].u_obj); + const char *protocol = mp_obj_str_get_str(args[ARG_protocol].u_obj); + + return common_hal_mdns_server_find(self, service_type, protocol, timeout); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mdns_server_find_obj, 1, mdns_server_find); + +//| def advertise_service(self, *, service_type: str, protocol: str, port: int) -> None: +//| """Respond to queries for the given service with the given port. +//| +//| :param str service_type: The service type such as "_http" +//| :param str protocol: The service protocol such as "_tcp" +//| :param int port: The port used by the service""" +//| ... +//| +STATIC mp_obj_t mdns_server_advertise_service(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mdns_server_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + + enum { ARG_service_type, ARG_protocol, ARG_port }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_service_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const char *service_type = mp_obj_str_get_str(args[ARG_service_type].u_obj); + const char *protocol = mp_obj_str_get_str(args[ARG_protocol].u_obj); + + common_hal_mdns_server_advertise_service(self, service_type, protocol, args[ARG_port].u_int); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mdns_server_advertise_service_obj, 1, mdns_server_advertise_service); + +STATIC const mp_rom_map_elem_t mdns_server_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mdns_server_hostname_obj) }, + { MP_ROM_QSTR(MP_QSTR_instance_name), MP_ROM_PTR(&mdns_server_instance_name_obj) }, + + { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&mdns_server_find_obj) }, + { MP_ROM_QSTR(MP_QSTR_advertise_service), MP_ROM_PTR(&mdns_server_advertise_service_obj) }, + + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mdns_server_deinit_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mdns_server_locals_dict, mdns_server_locals_dict_table); + +const mp_obj_type_t mdns_server_type = { + .base = { &mp_type_type }, + .name = MP_QSTR_Server, + .make_new = mdns_server_make_new, + .locals_dict = (mp_obj_t)&mdns_server_locals_dict, +}; diff --git a/shared-bindings/mdns/Server.h b/shared-bindings/mdns/Server.h new file mode 100644 index 0000000000..741cced9a0 --- /dev/null +++ b/shared-bindings/mdns/Server.h @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * 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. + */ + +#pragma once + +#include + +#include "common-hal/mdns/Server.h" + +extern const mp_obj_type_t mdns_server_type; + +void common_hal_mdns_server_construct(mdns_server_obj_t *self, mp_obj_t network_interface); +void common_hal_mdns_server_deinit(mdns_server_obj_t *self); +bool common_hal_mdns_server_deinited(mdns_server_obj_t *self); +const char * common_hal_mdns_server_get_hostname(mdns_server_obj_t *self); +void common_hal_mdns_server_set_hostname(mdns_server_obj_t *self, const char *hostname); +const char * common_hal_mdns_server_get_instance_name(mdns_server_obj_t *self); +void common_hal_mdns_server_set_instance_name(mdns_server_obj_t *self, const char *instance_name); +mp_obj_t common_hal_mdns_server_find(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_float_t timeout); +void common_hal_mdns_server_advertise_service(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_int_t port); diff --git a/shared-bindings/mdns/__init__.c b/shared-bindings/mdns/__init__.c new file mode 100644 index 0000000000..9752a3b7ff --- /dev/null +++ b/shared-bindings/mdns/__init__.c @@ -0,0 +1,56 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Dan Halbert for Adafruit Industries + * + * 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 "py/objexcept.h" +#include "py/runtime.h" +#include "shared-bindings/mdns/__init__.h" +#include "shared-bindings/mdns/Server.h" +#include "shared-bindings/mdns/RemoteService.h" + +//| """Multicast Domain Name Service +//| +//| The `mdns` module provides basic support for multicast domain name services. +//| Basic use provides hostname resolution under the .local TLD. This module +//| also supports DNS Service Discovery that allows for discovering other hosts +//| that provide a desired service.""" +//| + +STATIC const mp_rom_map_elem_t mdns_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mdns) }, + { MP_ROM_QSTR(MP_QSTR_Server), MP_ROM_PTR(&mdns_server_type) }, + { MP_ROM_QSTR(MP_QSTR_RemoteService), MP_ROM_PTR(&mdns_remoteservice_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mdns_module_globals, mdns_module_globals_table); + +const mp_obj_module_t mdns_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mdns_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_mdns, mdns_module, CIRCUITPY_MDNS); diff --git a/shared-bindings/mdns/__init__.h b/shared-bindings/mdns/__init__.h new file mode 100644 index 0000000000..d6722851c7 --- /dev/null +++ b/shared-bindings/mdns/__init__.h @@ -0,0 +1,27 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * 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. + */ + +#pragma once diff --git a/tools/ci_check_duplicate_usb_vid_pid.py b/tools/ci_check_duplicate_usb_vid_pid.py index 51eac31f03..0b84445ef1 100644 --- a/tools/ci_check_duplicate_usb_vid_pid.py +++ b/tools/ci_check_duplicate_usb_vid_pid.py @@ -51,6 +51,7 @@ DEFAULT_IGNORELIST = [ "unexpectedmaker_feathers2_prerelease", "espressif_kaluga_1", "espressif_kaluga_1.3", + "espressif_esp32s2_devkitc_1_n4", "espressif_esp32s2_devkitc_1_n4r2", "espressif_esp32s3_devkitc_1_n8", "espressif_esp32s3_devkitc_1_n8r2", From 6f0d62d85e8e918529c4e0868ebd2abd4eca9d83 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 18 Mar 2022 12:05:54 -0700 Subject: [PATCH 2/5] Formatting and shrink build size on C3 --- ports/espressif/common-hal/mdns/RemoteService.c | 8 ++++---- ports/espressif/common-hal/mdns/Server.c | 6 +++--- ports/espressif/mpconfigport.mk | 7 ++++--- shared-bindings/mdns/RemoteService.c | 1 - shared-bindings/mdns/RemoteService.h | 8 ++++---- shared-bindings/mdns/Server.h | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ports/espressif/common-hal/mdns/RemoteService.c b/ports/espressif/common-hal/mdns/RemoteService.c index 69c96fe0f8..e7eb93dc52 100644 --- a/ports/espressif/common-hal/mdns/RemoteService.c +++ b/ports/espressif/common-hal/mdns/RemoteService.c @@ -26,19 +26,19 @@ #include "shared-bindings/mdns/RemoteService.h" -const char * common_hal_mdns_remoteservice_get_service_type(mdns_remoteservice_obj_t *self) { +const char *common_hal_mdns_remoteservice_get_service_type(mdns_remoteservice_obj_t *self) { return self->result->service_type; } -const char * common_hal_mdns_remoteservice_get_protocol(mdns_remoteservice_obj_t *self) { +const char *common_hal_mdns_remoteservice_get_protocol(mdns_remoteservice_obj_t *self) { return self->result->proto; } -const char * common_hal_mdns_remoteservice_get_instance_name(mdns_remoteservice_obj_t *self) { +const char *common_hal_mdns_remoteservice_get_instance_name(mdns_remoteservice_obj_t *self) { return self->result->instance_name; } -const char * common_hal_mdns_remoteservice_get_hostname(mdns_remoteservice_obj_t *self) { +const char *common_hal_mdns_remoteservice_get_hostname(mdns_remoteservice_obj_t *self) { return self->result->hostname; } diff --git a/ports/espressif/common-hal/mdns/Server.c b/ports/espressif/common-hal/mdns/Server.c index eecd1ad66e..2f260bbde0 100644 --- a/ports/espressif/common-hal/mdns/Server.c +++ b/ports/espressif/common-hal/mdns/Server.c @@ -76,7 +76,7 @@ bool common_hal_mdns_server_deinited(mdns_server_obj_t *self) { return mdns_instance_name_set(NULL) == ESP_ERR_INVALID_STATE; } -const char * common_hal_mdns_server_get_hostname(mdns_server_obj_t *self) { +const char *common_hal_mdns_server_get_hostname(mdns_server_obj_t *self) { return self->hostname; } @@ -85,7 +85,7 @@ void common_hal_mdns_server_set_hostname(mdns_server_obj_t *self, const char *ho self->hostname = hostname; } -const char * common_hal_mdns_server_get_instance_name(mdns_server_obj_t *self) { +const char *common_hal_mdns_server_get_instance_name(mdns_server_obj_t *self) { if (self->instance_name == NULL) { return self->hostname; } @@ -121,7 +121,7 @@ mp_obj_t common_hal_mdns_server_find(mdns_server_obj_t *self, const char *servic // Don't error if we're out of memory. Instead, truncate the tuple. uint8_t added = 0; while (next != NULL) { - mdns_remoteservice_obj_t *service = gc_alloc(sizeof(mdns_remoteservice_obj_t), true, false); + mdns_remoteservice_obj_t *service = gc_alloc(sizeof(mdns_remoteservice_obj_t), GC_ALLOC_FLAG_HAS_FINALISER, false); if (service == NULL) { if (added == 0) { m_malloc_fail(sizeof(mdns_remoteservice_obj_t)); diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index 46e5bd3bb7..e70cc0f102 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -34,18 +34,19 @@ CIRCUITPY_ESPIDF ?= 1 CIRCUITPY_MODULE ?= none ifeq ($(IDF_TARGET),esp32c3) -CIRCUITPY_USB = 0 CIRCUITPY_ALARM = 0 +CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_BLEIO = 1 CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_COUNTIO = 0 -CIRCUITPY_ROTARYIO = 0 -CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_IMAGECAPTURE = 0 +CIRCUITPY_MDNS = 0 CIRCUITPY_PARALLELDISPLAY = 0 +CIRCUITPY_ROTARYIO = 0 CIRCUITPY_TOUCHIO ?= 1 CIRCUITPY_TOUCHIO_USE_NATIVE = 0 +CIRCUITPY_USB = 0 else ifeq ($(IDF_TARGET),esp32s3) CIRCUITPY_BLEIO = 1 CIRCUITPY_BLEIO_HCI = 0 diff --git a/shared-bindings/mdns/RemoteService.c b/shared-bindings/mdns/RemoteService.c index 4e1c63099d..2c8c9f6fd7 100644 --- a/shared-bindings/mdns/RemoteService.c +++ b/shared-bindings/mdns/RemoteService.c @@ -140,7 +140,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mdns_remoteservice_deinit_obj, mdns_remoteservi STATIC const mp_rom_map_elem_t mdns_remoteservice_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mdns_remoteservice_hostname_obj) }, { MP_ROM_QSTR(MP_QSTR_instance_name), MP_ROM_PTR(&mdns_remoteservice_instance_name_obj) }, - { MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&mdns_remoteservice_instance_name_obj) }, { MP_ROM_QSTR(MP_QSTR_service_type), MP_ROM_PTR(&mdns_remoteservice_service_type_obj) }, { MP_ROM_QSTR(MP_QSTR_protocol), MP_ROM_PTR(&mdns_remoteservice_protocol_obj) }, { MP_ROM_QSTR(MP_QSTR_port), MP_ROM_PTR(&mdns_remoteservice_port_obj) }, diff --git a/shared-bindings/mdns/RemoteService.h b/shared-bindings/mdns/RemoteService.h index 055ea24d2c..f751b683ed 100644 --- a/shared-bindings/mdns/RemoteService.h +++ b/shared-bindings/mdns/RemoteService.h @@ -33,9 +33,9 @@ extern const mp_obj_type_t mdns_remoteservice_type; -const char * common_hal_mdns_remoteservice_get_service_type(mdns_remoteservice_obj_t *self); -const char * common_hal_mdns_remoteservice_get_protocol(mdns_remoteservice_obj_t *self); -const char * common_hal_mdns_remoteservice_get_instance_name(mdns_remoteservice_obj_t *self); -const char * common_hal_mdns_remoteservice_get_hostname(mdns_remoteservice_obj_t *self); +const char *common_hal_mdns_remoteservice_get_service_type(mdns_remoteservice_obj_t *self); +const char *common_hal_mdns_remoteservice_get_protocol(mdns_remoteservice_obj_t *self); +const char *common_hal_mdns_remoteservice_get_instance_name(mdns_remoteservice_obj_t *self); +const char *common_hal_mdns_remoteservice_get_hostname(mdns_remoteservice_obj_t *self); mp_int_t common_hal_mdns_remoteservice_get_port(mdns_remoteservice_obj_t *self); void common_hal_mdns_remoteservice_deinit(mdns_remoteservice_obj_t *self); diff --git a/shared-bindings/mdns/Server.h b/shared-bindings/mdns/Server.h index 741cced9a0..a178e9bd2d 100644 --- a/shared-bindings/mdns/Server.h +++ b/shared-bindings/mdns/Server.h @@ -35,9 +35,9 @@ extern const mp_obj_type_t mdns_server_type; void common_hal_mdns_server_construct(mdns_server_obj_t *self, mp_obj_t network_interface); void common_hal_mdns_server_deinit(mdns_server_obj_t *self); bool common_hal_mdns_server_deinited(mdns_server_obj_t *self); -const char * common_hal_mdns_server_get_hostname(mdns_server_obj_t *self); +const char *common_hal_mdns_server_get_hostname(mdns_server_obj_t *self); void common_hal_mdns_server_set_hostname(mdns_server_obj_t *self, const char *hostname); -const char * common_hal_mdns_server_get_instance_name(mdns_server_obj_t *self); +const char *common_hal_mdns_server_get_instance_name(mdns_server_obj_t *self); void common_hal_mdns_server_set_instance_name(mdns_server_obj_t *self, const char *instance_name); mp_obj_t common_hal_mdns_server_find(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_float_t timeout); void common_hal_mdns_server_advertise_service(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_int_t port); From 543940e0a77c9ef47a97af06ce723e53b825aae7 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 18 Mar 2022 14:56:20 -0700 Subject: [PATCH 3/5] Fix the docs --- shared-bindings/mdns/RemoteService.c | 4 ++-- shared-bindings/mdns/Server.c | 2 +- shared-bindings/socketpool/SocketPool.c | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/shared-bindings/mdns/RemoteService.c b/shared-bindings/mdns/RemoteService.c index 2c8c9f6fd7..ecded5561f 100644 --- a/shared-bindings/mdns/RemoteService.c +++ b/shared-bindings/mdns/RemoteService.c @@ -33,12 +33,12 @@ #include "shared-bindings/mdns/RemoteService.h" //| class RemoteService: -//| """Encapsulates information about a remote service that was found during a query. This +//| """Encapsulates information about a remote service that was found during a search. This //| object may only be created by a `mdns.Server`. It has no user-visible constructor.""" //| //| def __init__(self) -> None: -//| """Cannot be instantiated directly. Use `mdns.Server.query`.""" +//| """Cannot be instantiated directly. Use `mdns.Server.find`.""" //| ... //| diff --git a/shared-bindings/mdns/Server.c b/shared-bindings/mdns/Server.c index 7ffc67f4d9..132d218aeb 100644 --- a/shared-bindings/mdns/Server.c +++ b/shared-bindings/mdns/Server.c @@ -135,7 +135,7 @@ const mp_obj_property_t mdns_server_instance_name_obj = { //| """Find all locally available remote services with the given service type and protocol. //| //| This doesn't allow for direct hostname lookup. To do that, use -//| `socketpool.SocketPool.getaddrinfo()` +//| `socketpool.SocketPool.getaddrinfo()`. //| //| :param str service_type: The service type such as "_http" //| :param str protocol: The service protocol such as "_tcp" diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index f427c759a4..13311bff21 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -91,13 +91,13 @@ STATIC mp_obj_t socketpool_socketpool_socket(size_t n_args, const mp_obj_t *pos_ } MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_socket_obj, 1, socketpool_socketpool_socket); -//| def getaddrinfo(host: str, port: int, family: int = 0, type: int = 0, proto: int = 0, flags: int = 0) -> Tuple[int, int, int, str, Tuple[str, int]]: -//| """Gets the address information for a hostname and port +//| def getaddrinfo(host: str, port: int, family: int = 0, type: int = 0, proto: int = 0, flags: int = 0) -> Tuple[int, int, int, str, Tuple[str, int]]: +//| """Gets the address information for a hostname and port //| -//| Returns the appropriate family, socket type, socket protocol and -//| address information to call socket.socket() and socket.connect() with, -//| as a tuple.""" -//| ... +//| Returns the appropriate family, socket type, socket protocol and +//| address information to call socket.socket() and socket.connect() with, +//| as a tuple.""" +//| ... //| STATIC mp_obj_t socketpool_socketpool_getaddrinfo(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_host, ARG_port, ARG_family, ARG_type, ARG_proto, ARG_flags }; From 92d946fcac55da391c3cbff182af88e493dd40e5 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 21 Mar 2022 10:15:46 -0700 Subject: [PATCH 4/5] Guard against NULL result --- ports/espressif/common-hal/mdns/RemoteService.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ports/espressif/common-hal/mdns/RemoteService.c b/ports/espressif/common-hal/mdns/RemoteService.c index e7eb93dc52..1d80c738bd 100644 --- a/ports/espressif/common-hal/mdns/RemoteService.c +++ b/ports/espressif/common-hal/mdns/RemoteService.c @@ -27,22 +27,37 @@ #include "shared-bindings/mdns/RemoteService.h" const char *common_hal_mdns_remoteservice_get_service_type(mdns_remoteservice_obj_t *self) { + if (self->result == NULL) { + return ""; + } return self->result->service_type; } const char *common_hal_mdns_remoteservice_get_protocol(mdns_remoteservice_obj_t *self) { + if (self->result == NULL) { + return ""; + } return self->result->proto; } const char *common_hal_mdns_remoteservice_get_instance_name(mdns_remoteservice_obj_t *self) { + if (self->result == NULL) { + return ""; + } return self->result->instance_name; } const char *common_hal_mdns_remoteservice_get_hostname(mdns_remoteservice_obj_t *self) { + if (self->result == NULL) { + return ""; + } return self->result->hostname; } mp_int_t common_hal_mdns_remoteservice_get_port(mdns_remoteservice_obj_t *self) { + if (self->result == NULL) { + return 0; + } return self->result->port; } From 1ac44a0760092ed8632b2d02031c92e26309bcb1 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 21 Mar 2022 10:49:07 -0700 Subject: [PATCH 5/5] Add missing self in function doc --- shared-bindings/socketpool/SocketPool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index 13311bff21..447d2d7d78 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -91,7 +91,7 @@ STATIC mp_obj_t socketpool_socketpool_socket(size_t n_args, const mp_obj_t *pos_ } MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_socket_obj, 1, socketpool_socketpool_socket); -//| def getaddrinfo(host: str, port: int, family: int = 0, type: int = 0, proto: int = 0, flags: int = 0) -> Tuple[int, int, int, str, Tuple[str, int]]: +//| def getaddrinfo(self, host: str, port: int, family: int = 0, type: int = 0, proto: int = 0, flags: int = 0) -> Tuple[int, int, int, str, Tuple[str, int]]: //| """Gets the address information for a hostname and port //| //| Returns the appropriate family, socket type, socket protocol and