diff --git a/Makefile b/Makefile index d82aef2..7a8adc0 100644 --- a/Makefile +++ b/Makefile @@ -28,8 +28,8 @@ create_build_dir: mkdir -p $(BUILDDIR)/httpd SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c -SRCS += rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c rtl837x_init.c -SRCS += uip/timer.c uip/uip.c uip/uip_arp.c uip/uiplib.c uip/uip-fw.c uip/uip-neighbor.c uip/uip-split.c +SRCS += rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c rtl837x_init.c syslog.c +SRCS += uip/timer.c uip/uip.c uip/uip_arp.c uip/uiplib.c uip/uip-fw.c uip/uip-neighbor.c uip/uip-split.c udp_apps.c SRCS += httpd/httpd.c httpd/page_impl.c OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel} DEPS := ${SRCS:%.c=$(BUILDDIR)/%.d} diff --git a/cmd_editor.c b/cmd_editor.c index 2a96e11..9a837e9 100644 --- a/cmd_editor.c +++ b/cmd_editor.c @@ -197,7 +197,7 @@ void cmd_edit(void) __banked if (cmd_line_len) cmd_available = 1; else - print_string("\n> "); + print_cmd_prompt(); cursor = 0; cmd_line_len = 0; history_editptr = 0xffff; diff --git a/cmd_parser.c b/cmd_parser.c index cf66829..2bc5595 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -15,6 +15,7 @@ #include "rtl837x_igmp.h" #include "rtl837x_bandwidth.h" #include "dhcp.h" +#include "syslog.h" #include "uip/uip.h" #include "version.h" @@ -1188,6 +1189,52 @@ err: print_string("usage: bw [in|out|status] [|off|drop|fc]\n"); } +void parse_syslog(void) +{ + if (cmd_words_len < 2) // no argument -> print status + { + print_string("Current syslog status: "); + if (syslog_state.enabled) { + print_string("enabled, sending to "); + itoa(syslog_state.server_ip[0]); write_char('.'); itoa(syslog_state.server_ip[1]); write_char('.'); + itoa(syslog_state.server_ip[2]); write_char('.'); itoa(syslog_state.server_ip[3]); + write_char('\n'); + } else { + print_string("disabled\n"); + } + return; + } + + if (cmd_compare(1, "on")) { + syslog_start(); + } else if (cmd_compare(1, "off")){ + syslog_stop(); + } else if (cmd_compare(1, "ip")) { + if (cmd_words_len < 3) { // no additional arguemnt -> print current ip + print_string("Current syslog IP: "); + itoa(syslog_state.server_ip[0]); write_char('.'); itoa(syslog_state.server_ip[1]); write_char('.'); + itoa(syslog_state.server_ip[2]); write_char('.'); itoa(syslog_state.server_ip[3]); + return; + } else if (!parse_ip(cmd_words_b[2])) { + uint8_t was_enabled = syslog_state.enabled; + if (was_enabled) + syslog_stop(); + print_string("Setting new syslog IP.\n"); + syslog_state.server_ip[0] = ip[0]; syslog_state.server_ip[1] = ip[1]; + syslog_state.server_ip[2] = ip[2]; syslog_state.server_ip[3] = ip[3]; + if (was_enabled) + syslog_start(); + } else { + print_string("Invalid IP address\n"); + } + } + else + { + print_string("Error: syslog [on|off|ip [ip-address]]\n"); + print_string(" on/off enables or disables syslog, ip sets the syslog server IP address\n"); + } +} + // Parse command into words // cmd_words_len contains the number of words found. // cmd_words_b[] contains only start of a word offset. @@ -1339,6 +1386,8 @@ void cmd_parser(void) __banked parse_port(); } else if (cmd_compare(0, "mtu")) { parse_mtu(); + } else if (cmd_compare(0, "syslog")) { + parse_syslog(); } else if (cmd_compare(0, "ip")) { if (cmd_compare(1, "dhcp")) { dhcp_start(); diff --git a/dhcp.c b/dhcp.c index d9176fd..1884501 100644 --- a/dhcp.c +++ b/dhcp.c @@ -348,8 +348,10 @@ void dhcp_stop(void) __banked } -void dhcp_callback(void) __banked +void dhcp_callback(uint16_t lport) __banked { + if (lport != HTONS(DHCPC_CLIENT_PORT)) // Is this call for us? If not, ignore it + return; if (!dhcp_state.state) return; if (uip_closed()) { diff --git a/dhcp.h b/dhcp.h index 991361b..f51feb0 100644 --- a/dhcp.h +++ b/dhcp.h @@ -16,7 +16,7 @@ void dhcp_start(void) __banked; void dhcp_stop(void) __banked; // void dhcp_periodic(void) __banked; -void dhcp_callback(void) __banked; +void dhcp_callback(uint16_t lport) __banked; struct dhcp_state { @@ -40,9 +40,4 @@ struct dhcp_state { typedef struct dhcp_state uip_udp_appstate_t; -/* Finally we define the application function to be called by uIP. */ -#ifndef UIP_UDP_APPCALL -#define UIP_UDP_APPCALL dhcp_callback -#endif /* UIP_APPCALL */ - #endif diff --git a/html/system.html b/html/system.html index eb74754..fe6c619 100644 --- a/html/system.html +++ b/html/system.html @@ -16,6 +16,7 @@
+
@@ -56,6 +57,17 @@
+
+

Console Command

+ + +
+

+ Be careful when entering console commands, you can lock yourself out!
+ + +
+ diff --git a/html/system.js b/html/system.js index c39f6fb..807e407 100644 --- a/html/system.js +++ b/html/system.js @@ -27,6 +27,20 @@ async function ipSub() { } } +async function cmdSub() { + var cmd = document.getElementById('console_cmd').value; + try { + const response = await fetch('/cmd', { + method: 'POST', + body: cmd + }); + console.log('Completed!', response); + } catch(err) { + console.error(`Error: ${err}`); + } +} + + async function sendConfig(c) { const form = new FormData(); form.append("MAX_FILE_SIZE", "4096"); diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 09c60b0..e9f8082 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -13,11 +13,11 @@ #include "version.h" #include "machine.h" #include "page_impl.h" +#include "syslog.h" // #define DEBUG #include "debug.h" - #define L2_MAX_TRANSFER 30 #pragma codeseg BANK1 @@ -227,6 +227,11 @@ void send_basic_info(void) itoa_html(uip_netmask[0] >> 8); char_to_html('.'); itoa_html(uip_netmask[1]); char_to_html('.'); itoa_html(uip_netmask[1] >> 8); + slen += strtox(outbuf + slen, "\",\"syslog_server_ip\":\""); + itoa_html(syslog_state.server_ip[0]); char_to_html('.'); + itoa_html(syslog_state.server_ip[1]); char_to_html('.'); + itoa_html(syslog_state.server_ip[2]); char_to_html('.'); + itoa_html(syslog_state.server_ip[3]); slen += strtox(outbuf + slen, "\",\"mac_address\":\""); byte_to_html(uip_ethaddr.addr[0]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[1]); char_to_html(':'); diff --git a/rtl837x_common.h b/rtl837x_common.h index d47bede..dbb39a8 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -110,6 +110,7 @@ extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; extern __xdata struct uip_eth_addr uip_ethaddr; // Headers for calls in the common code area (HOME/BANK0) +void print_string_no_syslog(__code char *p); void print_string(__code char *p); void print_string_x(__xdata char *p); void print_long(uint32_t a); @@ -118,6 +119,7 @@ void print_byte(uint8_t a); void itoa(uint8_t v); void print_sfr_data(void); void print_phy_data(void); +void print_cmd_prompt(void); void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v); void phy_write(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t v); void phy_read(uint8_t phy_id, uint8_t dev_id, uint16_t reg); @@ -130,6 +132,7 @@ void sds_read(uint8_t sds_id, uint8_t page, uint8_t reg); void sds_write_v(uint8_t sds_id, uint8_t page, uint8_t reg, uint16_t v); void delay(uint16_t t); void sleep(uint16_t t); +void write_char_no_syslog(char c); void write_char(char c); void print_reg(uint16_t reg); uint8_t sfp_read_reg(uint8_t slot, uint8_t reg); diff --git a/rtl837x_flash.h b/rtl837x_flash.h index 2267b23..60de64f 100644 --- a/rtl837x_flash.h +++ b/rtl837x_flash.h @@ -13,3 +13,4 @@ void flash_write_bytes(__xdata uint8_t *ptr); __code char* get_flash_size_str(void); #endif + diff --git a/rtl837x_pins.c b/rtl837x_pins.c index a6cbe06..90015b7 100644 --- a/rtl837x_pins.c +++ b/rtl837x_pins.c @@ -2,7 +2,10 @@ #include "rtl837x_common.h" #include "rtl837x_regs.h" -uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) { +#pragma codeseg BANK2 +#pragma constseg BANK2 + +uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) __banked { switch (sda_pin) { case GPIO47_I2C_SDA0: return 0; @@ -19,7 +22,7 @@ uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) { } } -uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) { +uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) __banked{ switch (scl_pin) { case GPIO46_I2C_SCL0: return 0; @@ -35,18 +38,18 @@ uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) { } /* Returns RTL837X_REG_GPIO_XX_OUTPUT register address */ -static uint16_t gpio_output_reg(uint8_t pin) { +static uint16_t gpio_output_reg(uint8_t pin) __banked{ return pin < 32 ? RTL837X_REG_GPIO_00_31_OUTPUT : RTL837X_REG_GPIO_32_63_OUTPUT; } /* Returns RTL837X_REG_GPIO_XX_DIRECTION register address */ -static uint16_t gpio_direction_reg(uint8_t pin) { +static uint16_t gpio_direction_reg(uint8_t pin) __banked { return pin < 32 ? RTL837X_REG_GPIO_00_31_DIRECTION : RTL837X_REG_GPIO_32_63_DIRECTION; } /* Enable GPIO functions for pin */ -static void gpio_mux_setup(uint8_t pin) +static void gpio_mux_setup(uint8_t pin) __banked { // Some GPIOs require setting MUX registers to enable GPIO switch (pin) { @@ -94,7 +97,7 @@ static void gpio_mux_setup(uint8_t pin) } } -void gpio_input_setup(uint8_t pin) { +void gpio_input_setup(uint8_t pin) __banked { if (pin == GPIO_NA) { return; } @@ -103,7 +106,7 @@ void gpio_input_setup(uint8_t pin) { reg_bit_clear(gpio_direction_reg(pin), (pin % 32)); } -void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val) { +void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val) __banked{ if (pin == GPIO_NA) { return; } diff --git a/rtl837x_pins.h b/rtl837x_pins.h index b8768f7..9f84226 100644 --- a/rtl837x_pins.h +++ b/rtl837x_pins.h @@ -72,22 +72,22 @@ #define GPIO_NA 0xFF /* Convert SDA PIN GPIO to I2C bus number */ -uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin); +uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) __banked; /* Convert SCL PIN GPIO to I2C bus number */ -uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin); +uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) __banked; /* * Setup a GPIO pin as input * pin: GPIO pin number 0-63 */ -void gpio_input_setup(uint8_t pin); +void gpio_input_setup(uint8_t pin) __banked; /* * Setup a GPIO pin as output * pin: GPIO pin number 0-63 * initial_val: 1 for bit set in RTL837X_REG_GPIO_xx_OUTPUT, 0 for bit not set */ -void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val); +void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val) __banked; #endif diff --git a/rtl837x_port.c b/rtl837x_port.c index 4c12a51..ba22a0e 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -387,7 +387,7 @@ void port_l2_setup(void) __banked void port_stats_print(void) __banked { - print_string("\n Port\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n"); + print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n"); for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { write_char('0' + machine.log_to_phys_port[i]); write_char('\t'); diff --git a/rtlplayground.c b/rtlplayground.c index 2be13b1..81cbc6e 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -24,6 +24,7 @@ #include "uip/uip_arp.h" #include "machine.h" #include "phy.h" +#include "syslog.h" extern __code const struct machine machine; extern __xdata uint32_t flash_size; @@ -216,7 +217,7 @@ void isr_serial(void) __interrupt(4) } -void write_char(char c) +void write_char_no_syslog(char c) { do { } while (tx_buf_empty == 0); @@ -230,6 +231,17 @@ void write_char(char c) SBUF = c; } +void write_char(char c) +{ + write_char_no_syslog(c); + + if (syslog_state.enabled) { + logbuf[syslog_state.writeptr++] = c; + syslog_state.writeptr &= (LOGBUF_SIZE - 1); + if (c == '\n') + syslog_state.line_available = 1; + } +} void itoa(uint8_t v) { @@ -253,6 +265,12 @@ void print_string(__code char *p) write_char(*p++); } +void print_string_no_syslog(__code char *p) +{ + while (*p) + write_char_no_syslog(*p++); +} + void print_string_x(__xdata char *p) { while (*p) @@ -350,6 +368,11 @@ void print_byte(uint8_t a) write_char(low); } +void print_cmd_prompt(void) +{ + print_string_no_syslog("\n> "); +} + /* * External IRQ 0 Service Routine: Called on link change? * Note that all registers are being put on the STACK because of calling a subroutine @@ -1376,7 +1399,7 @@ void idle(void) cmd_tokenize(); if (err_status == ERR_OK) cmd_parser(); - print_string("\n> "); + print_cmd_prompt(); } } @@ -1985,6 +2008,8 @@ void main(void) check_and_flash_update_image(); + syslog_init(); + #ifdef DEBUG // This register seems to work on the RTL8373 only if also the SDS // Is correctly configured. Therefore, we can test it, here... @@ -2031,12 +2056,13 @@ void main(void) early_boot_handle_button(); execute_config(); - print_string("\n> "); + print_cmd_prompt(); idle_ready = 1; set_sys_led_state(SYS_LED_ON); cmd_editor_init(); + while (1) { cmd_edit(); idle(); // Enter Idle mode until interrupt occurs diff --git a/syslog.c b/syslog.c new file mode 100644 index 0000000..ad97fd2 --- /dev/null +++ b/syslog.c @@ -0,0 +1,105 @@ +#include "machine.h" +#include "syslog.h" +#include "uip/uip.h" +#include "rtl837x_common.h" + +#pragma codeseg BANK2 +#pragma constseg BANK2 + +#define SYSLOG_P ((__xdata uint8_t *)uip_appdata) + +__xdata char logbuf[LOGBUF_SIZE]; +__xdata struct syslog_state syslog_state; +__xdata uip_ipaddr_t server_ip; + +#define state syslog_state + +void syslog_init(void) __banked +{ + state.enabled = 0; + state.syslog_conn = 0; + state.writeptr = 0; + state.readptr = 0; + state.line_available = 0; + state.server_ip[0] = 0; state.server_ip[1] = 0; state.server_ip[2] = 0; state.server_ip[3] = 0;// Default to 0.0.0.0 +} + +void syslog_start(void) __banked +{ + if (state.syslog_conn == 0) { + uip_ipaddr(server_ip, state.server_ip[0], state.server_ip[1], state.server_ip[2], state.server_ip[3]); + state.syslog_conn = uip_udp_new(&server_ip, HTONS(514)); + if (state.syslog_conn == 0) { + print_string_no_syslog("Failed to create a new UDP client\n"); + return; + } + print_string_no_syslog("Started syslog to IP "); + itoa(state.server_ip[0]); write_char('.'); itoa(state.server_ip[1]); write_char('.'); + itoa(state.server_ip[2]); write_char('.'); itoa(state.server_ip[3]); write_char('\n'); + state.enabled = 1; + } + else { + print_string_no_syslog("Syslog is already running\n"); + } +} + +void syslog_stop(void) __banked +{ + state.enabled = 0; + if (state.syslog_conn != 0) { + uip_udp_remove(state.syslog_conn); + state.syslog_conn = 0; + print_string_no_syslog("Stopped syslog\n"); + } else { + print_string_no_syslog("Syslog is not running\n"); + } +} + +void syslog_callback(uint16_t lport) __banked +{ + if (lport != state.syslog_conn->lport) + return; + + if ((state.readptr != state.writeptr) && state.line_available) + { + int16_t log_size = state.writeptr - state.readptr; + if (log_size < 0) + log_size += LOGBUF_SIZE; + + // Skipping linefeeds at the start of the log line + uint16_t log_start = state.readptr; + while (log_size > 0 && logbuf[log_start] == '\n') { + log_start = (log_start + 1) & (LOGBUF_SIZE - 1); + log_size--; + } + + // Skipping linefeeds and whitespaces at the end of the log line + uint16_t log_end = state.writeptr; + while ( (log_size > 0) && + ((logbuf[(log_end-1) & (LOGBUF_SIZE - 1)] == '\n') || + (logbuf[(log_end-1) & (LOGBUF_SIZE - 1)] == ' '))) + { + log_end = (log_end - 1) & (LOGBUF_SIZE - 1); + log_size--; + } + + if (log_size == 0) { + state.readptr = state.writeptr; + state.line_available = 0; + return; + } + + memcpyc(SYSLOG_P, "<14>", 4); // Syslog priority prefix + + if (log_end < log_start) { + memcpy(SYSLOG_P + 4, logbuf + log_start, LOGBUF_SIZE - log_start); + memcpy(SYSLOG_P + 4 + LOGBUF_SIZE - log_start, logbuf, log_end); + } else { + memcpy(SYSLOG_P + 4, logbuf + log_start, log_end - log_start); + } + + uip_udp_send(log_size+4); + state.readptr = state.writeptr; + state.line_available = 0; + } +} diff --git a/syslog.h b/syslog.h new file mode 100644 index 0000000..f3666da --- /dev/null +++ b/syslog.h @@ -0,0 +1,26 @@ +#ifndef _SYSLOG_H_ +#define _SYSLOG_H_ + +#include + +#define LOGBUF_SIZE 512 + +struct syslog_state { + uint8_t enabled; + uint8_t line_available; + uint16_t writeptr ; + uint16_t readptr; + uint8_t server_ip[4]; + + struct uip_udp_conn *syslog_conn; +}; + +extern __xdata struct syslog_state syslog_state; +extern __xdata char logbuf[LOGBUF_SIZE]; + +void syslog_init(void) __banked; +void syslog_start(void) __banked; +void syslog_stop(void) __banked; +void syslog_callback(uint16_t lport) __banked; + +#endif diff --git a/udp_apps.c b/udp_apps.c new file mode 100644 index 0000000..f2c9c55 --- /dev/null +++ b/udp_apps.c @@ -0,0 +1,9 @@ + +#include "uip/uip.h" +#include "udp_apps.h" + +void udp_callbacks(void) +{ + dhcp_callback(uip_udp_conn->lport); // let the application decide if this is for it or not + syslog_callback(uip_udp_conn->lport); // let the application decide if this is for it or not +} \ No newline at end of file diff --git a/udp_apps.h b/udp_apps.h new file mode 100644 index 0000000..1f842ce --- /dev/null +++ b/udp_apps.h @@ -0,0 +1,13 @@ +#ifndef _UDPAPPS_H_ +#define _UDPAPPS_H_ + +#include "dhcp.h" +#include "syslog.h" + +void udp_callbacks(void); + +#ifndef UIP_UDP_APPCALL +#define UIP_UDP_APPCALL udp_callbacks +#endif /* UIP_UDP_APPCALL */ + +#endif diff --git a/uip/uip-conf.h b/uip/uip-conf.h index a413c83..384f7fa 100644 --- a/uip/uip-conf.h +++ b/uip/uip-conf.h @@ -153,7 +153,7 @@ typedef unsigned short uip_stats_t; our project. */ /*#include "smtp.h"*/ #include "httpd.h" -#include "dhcp.h" +#include "udp_apps.h" /*#include "telnetd.h"*/ /*#include "webserver.h" */ /*#include "dhcpc.h"*/ diff --git a/uip/uip.c b/uip/uip.c index a15787a..ee07a04 100644 --- a/uip/uip.c +++ b/uip/uip.c @@ -234,7 +234,7 @@ __xdata struct uip_stats uip_stat; #endif /* UIP_STATISTICS == 1 */ #if UIP_LOGGING == 1 -#define UIP_LOG(m) print_string(m) +#define UIP_LOG(m) print_string_no_syslog(m); #else #define UIP_LOG(m) #endif /* UIP_LOGGING == 1 */