From 3ec966b2f374f7726a194a218308837e6b366ea6 Mon Sep 17 00:00:00 2001 From: Terje Io Date: Tue, 8 Jun 2021 15:51:31 +0200 Subject: [PATCH] Fixed $70 handling, added patch for low level SD card library --- README.md | 10 ++++-- grblHAL_Teensy4/src/enet.c | 69 +++++++++++++------------------------ patches/sd_sdhc.zip | Bin 0 -> 9726 bytes 3 files changed, 32 insertions(+), 47 deletions(-) create mode 100644 patches/sd_sdhc.zip diff --git a/README.md b/README.md index 3a26151..da845d2 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,13 @@ to `#define USE_MSC 0 // will be used in sd_msc.cpp` -or add the MSC library as well \(not needed\). +or add the MSC library as well \(not needed\). 2021-06-08: This is now changed in the latest version. + +**NOTE:** + +If enabling ftp transfer to the SD card then [utility/sd_sdhc.c](https://github.com/WMXZ-EU/uSDFS/blob/master/src/utility/sd_sdhc.c) has to be replaced with [this patched](patches/sd_sdhc.zip) version \(zip download\). +I submitted a PR for this but it was rejected with no explanation, this is why I have added it here. The maintainer has made a similar change but that does not fix the underlying issue, and it may even crash the controller. +In addition to this [ffconf.h](https://github.com/WMXZ-EU/uSDFS/blob/master/src/ffconf.h) has to be edited, `#define FF_FS_RPATH` value has to be changed to 2 \(from 1\) or you will get a compiler error. --- @@ -50,4 +56,4 @@ Download the libraries above as zip files and add to your Arduino installation w 3 Number of digital input pins available is reduced when the [Encoder plugin](https://github.com/grblHAL/Plugin_encoder/blob/master/README.md) is added to the build. --- -2021-05-09 +2021-06-08 diff --git a/grblHAL_Teensy4/src/enet.c b/grblHAL_Teensy4/src/enet.c index 0ce6b4b..e6ac89f 100644 --- a/grblHAL_Teensy4/src/enet.c +++ b/grblHAL_Teensy4/src/enet.c @@ -36,16 +36,15 @@ #include "grbl/report.h" #include "grbl/nvs_buffer.h" -#include "networking/ftpd.h" -#include "networking/TCPStream.h" -#include "networking/WsStream.h" +#include "networking/networking.h" static volatile bool linkUp = false; static char IPAddress[IP4ADDR_STRLEN_MAX]; -static network_services_t services = {0}; +static network_services_t services = {0}, allowed_services; static nvs_address_t nvs_address; static network_settings_t ethernet, network; -static on_report_options_ptr on_report_options; +static on_report_options_ptr on_report_options;; +static char netservices[30] = ""; // must be large enough to hold all service names static void report_options (bool newopt) { @@ -169,35 +168,15 @@ static void ethernet_settings_load (void); static void ethernet_settings_restore (void); static status_code_t ethernet_set_ip (setting_id_t setting, char *value); static char *ethernet_get_ip (setting_id_t setting); +static status_code_t ethernet_set_services (setting_id_t setting, uint_fast16_t int_value); +static uint32_t ethernet_get_services (setting_id_t id); static const setting_group_detail_t ethernet_groups [] = { { Group_Root, Group_Networking, "Networking" } }; -#if TELNET_ENABLE && WEBSOCKET_ENABLE && FTP_ENABLE -static const char netservices[] = "Telnet,Websocket,FTP"; -static const char servicemap[] = "11"; -#endif -#if TELNET_ENABLE && WEBSOCKET_ENABLE && HTTP_ENABLE -static const char netservices[] = "Telnet,Websocket,HTTP"; -static const char servicemap[] = "7"; -#endif -#if TELNET_ENABLE && WEBSOCKET_ENABLE && !FTP_ENABLE && !HTTP_ENABLE -static const char netservices[] = "Telnet,Websocket"; -static const char servicemap[] = "2"; -#endif -#if TELNET_ENABLE && !WEBSOCKET_ENABLE && !HTTP_ENABLE -static const char netservices[] = "Telnet"; -static const char servicemap[] = "1"; -#endif - -static const network_services_t aserv = { - .telnet = 1, - .ftp = 1 -}; - PROGMEM static const setting_detail_t ethernet_settings[] = { - { Setting_NetworkServices, Group_Networking, "Network Services", NULL, Format_Bitfield, netservices, NULL, NULL, Setting_NonCore, ðernet.services.mask, NULL, NULL }, + { Setting_NetworkServices, Group_Networking, "Network Services", NULL, Format_Bitfield, netservices, NULL, NULL, Setting_NonCoreFn, ethernet_set_services, ethernet_get_services, NULL }, { Setting_Hostname, Group_Networking, "Hostname", NULL, Format_String, "x(64)", NULL, "64", Setting_NonCore, ethernet.hostname, NULL, NULL }, { Setting_IpMode, Group_Networking, "IP Mode", NULL, Format_RadioButtons, "Static,DHCP,AutoIP", NULL, NULL, Setting_NonCore, ðernet.ip_mode, NULL, NULL }, { Setting_IpAddress, Group_Networking, "IP Address", NULL, Format_IPv4, NULL, NULL, NULL, Setting_NonCoreFn, ethernet_set_ip, ethernet_get_ip, NULL }, @@ -287,6 +266,18 @@ static char *ethernet_get_ip (setting_id_t setting) return ip; } +static status_code_t ethernet_set_services (setting_id_t setting, uint_fast16_t int_value) +{ + ethernet.services.mask = int_value & allowed_services.mask; + + return Status_OK; +} + +static uint32_t ethernet_get_services (setting_id_t id) +{ + return (uint32_t)ethernet.services.mask; +} + void ethernet_settings_restore (void) { strcpy(ethernet.hostname, NETWORK_HOSTNAME); @@ -309,26 +300,10 @@ void ethernet_settings_restore (void) set_addr(ethernet.mask, &addr); #endif - ethernet.services.mask = 0; ethernet.telnet_port = NETWORK_TELNET_PORT; ethernet.http_port = NETWORK_HTTP_PORT; ethernet.websocket_port = NETWORK_WEBSOCKET_PORT; - -#if TELNET_ENABLE - ethernet.services.telnet = On; -#endif - -#if FTP_ENABLE - ethernet.services.ftp = On; -#endif - -#if HTTP_ENABLE - ethernet.services.http = On; -#endif - -#if WEBSOCKET_ENABLE - ethernet.services.websocket = On; -#endif + ethernet.services.mask = allowed_services.mask; hal.nvs.memcpy_to_nvs(nvs_address, (uint8_t *)ðernet, sizeof(network_settings_t), true); } @@ -337,6 +312,8 @@ static void ethernet_settings_load (void) { if(hal.nvs.memcpy_from_nvs((uint8_t *)ðernet, nvs_address, sizeof(network_settings_t), true) != NVS_TransferResult_OK) ethernet_settings_restore(); + + ethernet.services.mask &= allowed_services.mask; } bool grbl_enet_init (network_settings_t *settings) @@ -348,6 +325,8 @@ bool grbl_enet_init (network_settings_t *settings) details.on_get_settings = grbl.on_get_settings; grbl.on_get_settings = on_get_settings; + + allowed_services.mask = networking_get_services_list((char *)netservices).mask; } return nvs_address != 0; diff --git a/patches/sd_sdhc.zip b/patches/sd_sdhc.zip new file mode 100644 index 0000000000000000000000000000000000000000..1450076c4a28dd4782fe5c71b616cc959d02833e GIT binary patch literal 9726 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 M00027B>(^b0QW(SU;qFB literal 0 HcmV?d00001