├── assets-fx ├── icon.png └── img │ ├── fxconv-metadata.txt │ └── example.png ├── src ├── network.h ├── ui-keyboard.h ├── fxlibc │ ├── strstr.c │ ├── strcasestr.c │ ├── strncmp.c │ ├── memchr.c │ ├── strncasecmp.c │ ├── string_p.h │ ├── strstr_base.c │ ├── ctype.h │ └── string.h ├── scif.h ├── log.h ├── hayes.h ├── util.h ├── objectlog.h ├── uip │ ├── Makefile.include │ ├── irc.h │ ├── uip-neighbor.h │ ├── uiplib.c │ ├── uiplib.h │ ├── lc-switch.h │ ├── timer.h │ ├── clock.h │ ├── lc-addrlabels.h │ ├── memb.c │ ├── lc.h │ ├── timer.c │ ├── uip_arch.h │ ├── memb.h │ ├── uip_arp.h │ ├── uip-neighbor.c │ ├── irc.c │ ├── uip-fw.h │ ├── pt.h │ ├── psock.c │ ├── psock.h │ ├── uip_arp.c │ └── uip-fw.c ├── ui.h ├── hayes.c ├── network.c ├── clock-arch.h ├── slipdev.h ├── ringbuffer.h ├── main.c ├── log.c ├── clock-arch.c ├── scif.c ├── uip-conf.h ├── ui-keyboard.c ├── ui.c ├── slipdev.c └── objectlog.c ├── assets-cg ├── icon-sel.png ├── icon-uns.png └── img │ ├── fxconv-metadata.txt │ └── example.png ├── .gitignore ├── LICENSE ├── README.md ├── gint.patch ├── project.cfg └── Makefile /assets-fx/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manawyrm/fxIP/HEAD/assets-fx/icon.png -------------------------------------------------------------------------------- /src/network.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void network_init(); 4 | void network_poll(); 5 | -------------------------------------------------------------------------------- /assets-cg/icon-sel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manawyrm/fxIP/HEAD/assets-cg/icon-sel.png -------------------------------------------------------------------------------- /assets-cg/icon-uns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manawyrm/fxIP/HEAD/assets-cg/icon-uns.png -------------------------------------------------------------------------------- /assets-cg/img/fxconv-metadata.txt: -------------------------------------------------------------------------------- 1 | example.png: 2 | type: bopti-image 3 | name: img_example 4 | -------------------------------------------------------------------------------- /assets-fx/img/fxconv-metadata.txt: -------------------------------------------------------------------------------- 1 | example.png: 2 | type: bopti-image 3 | name: img_example 4 | -------------------------------------------------------------------------------- /assets-cg/img/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manawyrm/fxIP/HEAD/assets-cg/img/example.png -------------------------------------------------------------------------------- /assets-fx/img/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manawyrm/fxIP/HEAD/assets-fx/img/example.png -------------------------------------------------------------------------------- /src/ui-keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int ui_keycode_character(int keycode); 4 | int ui_handle_keyboard(); 5 | -------------------------------------------------------------------------------- /src/fxlibc/strstr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "string_p.h" 3 | 4 | char *strstr(char const *haystack, char const *needle) 5 | { 6 | return __strstr_base(haystack, needle, false); 7 | } 8 | -------------------------------------------------------------------------------- /src/scif.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdint.h" 3 | 4 | void scif_debug(); 5 | void scif_write(const void *data, uint16_t len); 6 | int scif_read(); 7 | void scif_init(); 8 | int scif_read_flush(); -------------------------------------------------------------------------------- /src/fxlibc/strcasestr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "string_p.h" 3 | 4 | char *strcasestr(char const *haystack, char const *needle) 5 | { 6 | return __strstr_base(haystack, needle, true); 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build files 2 | /build-fx 3 | /build-cg 4 | /*.g1a 5 | /*.g3a 6 | 7 | # Python bytecode 8 | __pycache__/ 9 | 10 | # Common IDE files 11 | *.sublime-project 12 | *.sublime-workspace 13 | .vscode 14 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void uip_log(char *msg); 5 | void fxip_log(const char *msg); 6 | void myprintf(const char *format, ...); 7 | void fxip_print_hexdump(const void *addr, uint16_t size); 8 | -------------------------------------------------------------------------------- /src/hayes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | int hayes_send_and_read(char *command, char *readbuf, uint16_t readbuflength); 5 | int hayes_read(char *readbuf, uint16_t readbuflength, int timeout, int ignore_echo); 6 | int hayes_send(char *command); -------------------------------------------------------------------------------- /src/fxlibc/strncmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int strncmp(const char *s1, const char *s2, size_t n) 4 | { 5 | if (n == 0) 6 | return (0); 7 | size_t i = -1; 8 | while (++i < n - 1 && s1[i] != '\0' && s2[i] != '\0' 9 | && s1[i] == s2[i]) ; 10 | return (s1[i] - s2[i]); 11 | } 12 | -------------------------------------------------------------------------------- /src/fxlibc/memchr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #ifndef __SUPPORT_ARCH_SH 3 | void *memchr(void const *_s, int c, size_t n) 4 | { 5 | char const *s = _s; 6 | 7 | for (size_t i = 0; i < n; i++) 8 | { 9 | if (s[i] == c) 10 | return (char *)&s[i]; 11 | } 12 | 13 | return NULL; 14 | } 15 | 16 | #endif /*__SUPPORT_ARCH_SH*/ 17 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) 4 | 5 | #define BIT(x) (1 << (x)) 6 | #define BITMASK(end, start) (((BIT(end + 1) >> start) - 1) << start) 7 | 8 | #define MMIO8(addr) (*(volatile uint8_t*)(addr)) 9 | #define MMIO16(addr) (*(volatile uint16_t*)(addr)) 10 | 11 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 12 | -------------------------------------------------------------------------------- /src/fxlibc/strncasecmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int strncasecmp(const char *s1, const char *s2, size_t n) 5 | { 6 | if (n == 0) 7 | return (0); 8 | size_t i = -1; 9 | while (++i < n - 1 && s1[i] != '\0' && s2[i] != '\0' 10 | && tolower(s1[i]) == tolower(s2[i])) ; 11 | return (tolower(s1[i]) - tolower(s2[i])); 12 | } 13 | -------------------------------------------------------------------------------- /src/fxlibc/string_p.h: -------------------------------------------------------------------------------- 1 | #ifndef __STRING_P_H__ 2 | # define __STRING_P_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | ** Search for __needle within __haystack using either brute-force or the Knuth- 10 | ** Morris-Pratt algorithm. Ignores case if __ignore_case == true. This is the 11 | ** base function for strstr and strcasestr. 12 | */ 13 | char *__strstr_base( 14 | char const *__haystack, 15 | char const *__needle, 16 | bool __ignore_case); 17 | 18 | #endif /*__STRING_P_H__*/ 19 | -------------------------------------------------------------------------------- /src/objectlog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "ringbuffer.h" 7 | 8 | typedef struct 9 | { 10 | ringbuffer_t ring; 11 | uint16_t ptr_first; 12 | uint16_t ptr_last; 13 | unsigned int num_entries; 14 | } objectlog_t; 15 | 16 | typedef long objectlog_iterator_t; 17 | 18 | typedef struct 19 | { 20 | const void *ptr; 21 | uint16_t len; 22 | } scatter_object_t; 23 | 24 | void objectlog_init(objectlog_t *log, void *storage, uint16_t size); 25 | uint16_t objectlog_write_object(objectlog_t *log, const void *data, uint16_t len); 26 | uint16_t objectlog_write_scattered_object(objectlog_t *log, const scatter_object_t *scatter_list); 27 | uint16_t objectlog_write_string(objectlog_t *log, const char *str); 28 | objectlog_iterator_t objectlog_iterator(objectlog_t *log, int object_idx); 29 | const void *objectlog_get_fragment(objectlog_t *log, objectlog_iterator_t iterator, uint8_t *len); 30 | objectlog_iterator_t objectlog_next(objectlog_t *log, objectlog_iterator_t iterator); 31 | long objectlog_get_object_size(objectlog_t *log, int object_idx); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tobias Mädel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/uip/Makefile.include: -------------------------------------------------------------------------------- 1 | 2 | 3 | ifdef APPS 4 | APPDIRS = $(foreach APP, $(APPS), ../apps/$(APP)) 5 | -include $(foreach APP, $(APPS), ../apps/$(APP)/Makefile.$(APP)) 6 | CFLAGS += $(addprefix -I../apps/,$(APPS)) 7 | endif 8 | 9 | ifndef CCDEP 10 | CCDEP = $(CC) 11 | endif 12 | ifndef CCDEPCFLAGS 13 | CCDEPCFLAGS = $(CFLAGS) 14 | endif 15 | ifndef OBJECTDIR 16 | OBJECTDIR = obj 17 | endif 18 | 19 | ifeq (${wildcard $(OBJECTDIR)},) 20 | DUMMY := ${shell mkdir $(OBJECTDIR)} 21 | endif 22 | 23 | 24 | vpath %.c . ../uip ../lib $(APPDIRS) 25 | 26 | $(OBJECTDIR)/%.o: %.c 27 | $(CC) $(CFLAGS) -c $< -o $@ 28 | 29 | $(OBJECTDIR)/%.d: %.c 30 | @set -e; rm -f $@; \ 31 | $(CCDEP) -MM $(CCDEPCFLAGS) $< > $@.$$$$; \ 32 | sed 's,\($*\)\.o[ :]*,$(OBJECTDIR)/\1.o $@ : ,g' < $@.$$$$ > $@; \ 33 | rm -f $@.$$$$ 34 | 35 | UIP_SOURCES=uip.c uip_arp.c uiplib.c psock.c timer.c uip-neighbor.c 36 | 37 | 38 | ifneq ($(MAKECMDGOALS),clean) 39 | -include $(addprefix $(OBJECTDIR)/,$(UIP_SOURCES:.c=.d) \ 40 | $(APP_SOURCES:.c=.d)) 41 | endif 42 | 43 | uip.a: ${addprefix $(OBJECTDIR)/, $(UIP_SOURCES:.c=.o)} 44 | $(AR) rcf $@ $^ 45 | 46 | apps.a: ${addprefix $(OBJECTDIR)/, $(APP_SOURCES:.c=.o)} 47 | $(AR) rcf $@ $^ 48 | -------------------------------------------------------------------------------- /src/uip/irc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "uipopt.h" 3 | #include "psock.h" 4 | 5 | void irc_init(void); 6 | 7 | /* Functions. */ 8 | void irc_configure(u16_t *server); 9 | 10 | void irc_appcall(void); 11 | void irc_done(unsigned char error); 12 | unsigned char irc_connect(u16_t *server); 13 | 14 | typedef enum { 15 | IRC_CONNECTION_NEW, 16 | IRC_CONNECTION_USER, 17 | IRC_CONNECTION_JOIN, 18 | IRC_CONNECTION_ESTABLISHED 19 | } irc_connection_state_t; 20 | 21 | uint8_t messagebuffer[256]; 22 | uint16_t messagelength; 23 | uint16_t printflength; 24 | 25 | typedef struct irc_state 26 | { 27 | u8_t state; 28 | irc_connection_state_t connection_state; 29 | 30 | uint8_t connected; 31 | struct psock psock; 32 | struct psock psock_out; 33 | 34 | uint8_t inputbuffer[128]; 35 | } uip_tcp_appstate_t; 36 | 37 | typedef struct 38 | { 39 | char *message; // :tungsten.libera.chat 250 asdfCasio :Highest connection count: 6972 (6971 clients) (71075 connections received) 40 | uint16_t length; 41 | 42 | char *prefix; // tungsten.libera.chat 43 | char *message_without_prefix; // 250 asdfCasio :Highest connection count: 6972 (6971 clients) (71075 connections received) 44 | char *command; // 250 45 | char *command_arguments; 46 | } irc_message; 47 | 48 | #ifndef UIP_APPCALL 49 | #define UIP_APPCALL irc_appcall 50 | #endif -------------------------------------------------------------------------------- /src/ui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "objectlog.h" 4 | 5 | #define UI_DISPLAY_PIXEL_X 128 6 | #define UI_DISPLAY_PIXEL_Y 64 7 | #define UI_DISPLAY_LINES 7 8 | #define UI_DISPLAY_CHARS 21 9 | 10 | int ui_handle_keyboard(); 11 | void ui_update(); 12 | void ui_update_logs(); 13 | void ui_init(); 14 | 15 | void ui_printf(int x, int y, int fg, const char * format, ...); 16 | 17 | typedef enum { 18 | PAGE_LOGS, 19 | PAGE_STATISTICS, 20 | PAGE_IRC_OVERVIEW, 21 | PAGE_IRC_CHANNEL 22 | } page_type_t; 23 | 24 | struct page; 25 | 26 | struct page 27 | { 28 | uint8_t id; 29 | uint8_t key; 30 | void (*render_callback)(struct page *page); 31 | uint8_t input_enabled; 32 | char *input_buffer; 33 | uint16_t input_buffer_size; 34 | uint16_t input_offset; 35 | uint16_t input_scroll_offset; 36 | void (*input_submit_callback)(struct page *page); 37 | uint16_t scroll_x; 38 | }; 39 | 40 | typedef struct page page_t; 41 | 42 | struct message_hdr 43 | { 44 | uint8_t page_id; 45 | uint8_t type; 46 | uint8_t channel; 47 | } __attribute__((packed)); 48 | typedef struct message_hdr message_hdr_t; 49 | 50 | void ui_render_logs(page_t *page); 51 | void ui_render_statistics(page_t *page); 52 | void ui_render_irc(page_t *page); 53 | const void *ui_objectlog_get_message(objectlog_t *log, int object_idx, unsigned offset, objectlog_iterator_t *riter, message_hdr_t *hdr, uint8_t *len); 54 | 55 | extern page_t *current_page; 56 | extern const page_t pages[4]; -------------------------------------------------------------------------------- /src/hayes.c: -------------------------------------------------------------------------------- 1 | #include "hayes.h" 2 | #include "util.h" 3 | 4 | uint8_t hayes_response_buffer[128]; 5 | uint16_t hayes_response_buffer_offset = 0; 6 | 7 | int hayes_send(char *command) 8 | { 9 | if (strlen(command) != 0) 10 | { 11 | scif_write(command, strlen(command)); 12 | scif_write("\r\n", 2); 13 | } 14 | } 15 | 16 | int hayes_read(char *readbuf, uint16_t readbuflength, int timeout, int ignore_echo) 17 | { 18 | hayes_response_buffer_offset = 0; 19 | 20 | uint8_t echo = ignore_echo; 21 | 22 | uint32_t start = clock_time(); 23 | 24 | while (1) 25 | { 26 | int byte = scif_read(); 27 | if (byte >= 0) 28 | { 29 | hayes_response_buffer[hayes_response_buffer_offset++] = byte; 30 | 31 | if (byte == '\n') 32 | { 33 | hayes_response_buffer[hayes_response_buffer_offset] = 0x00; 34 | if (echo == 0) 35 | { 36 | echo = 1; 37 | } 38 | else 39 | { 40 | memcpy(readbuf, hayes_response_buffer, MIN(hayes_response_buffer_offset + 1, readbuflength)); 41 | return 1; 42 | } 43 | 44 | hayes_response_buffer_offset = 0; 45 | } 46 | } 47 | 48 | if (timeout) 49 | { 50 | if (start + timeout < clock_time()) 51 | { 52 | fxip_log("timeout"); 53 | return 0; 54 | } 55 | } 56 | 57 | } 58 | } 59 | 60 | int hayes_send_and_read(char *command, char *readbuf, uint16_t readbuflength) 61 | { 62 | // flush all previous content in the read 63 | scif_read_flush(); 64 | 65 | hayes_send(command); 66 | 67 | return hayes_read(readbuf, readbuflength, 20, 0); 68 | } -------------------------------------------------------------------------------- /src/network.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "network.h" 5 | #include "uip/uip.h" 6 | #include "uip/timer.h" 7 | #include "clock-arch.h" 8 | 9 | #include "log.h" 10 | #include "slipdev.h" 11 | #include "ui.h" 12 | 13 | uip_ipaddr_t ipaddr; 14 | struct timer periodic_timer, arp_timer; 15 | 16 | void network_init() 17 | { 18 | slipdev_init(); 19 | timer_set(&periodic_timer, CLOCK_SECOND / 2); 20 | 21 | srand(rtc_ticks()); 22 | 23 | uip_init(); 24 | fxip_log("uip_init() done"); 25 | 26 | uip_ipaddr(ipaddr, 10,10,10,2); 27 | uip_sethostaddr(ipaddr); 28 | uip_ipaddr(ipaddr, 10,10,10,1); 29 | uip_setdraddr(ipaddr); 30 | uip_ipaddr(ipaddr, 255,255,255,0); 31 | uip_setnetmask(ipaddr); 32 | 33 | //httpd_init(); 34 | irc_init(); 35 | 36 | uip_ipaddr(ipaddr, 163,123,192,192); 37 | //uip_ipaddr(ipaddr, 10,10,10,1); 38 | irc_connect(ipaddr); 39 | 40 | fxip_log("app_init() done"); 41 | 42 | } 43 | 44 | void network_poll() 45 | { 46 | uip_len = slipdev_poll(); 47 | if(uip_len > 0) 48 | { 49 | uip_input(); 50 | /* If the above function invocation resulted in data that 51 | should be sent out on the network, the global variable 52 | uip_len is set to a value > 0. */ 53 | if(uip_len > 0) 54 | { 55 | slipdev_send(); 56 | } 57 | 58 | } 59 | else if(timer_expired(&periodic_timer)) 60 | { 61 | timer_reset(&periodic_timer); 62 | 63 | for(int i = 0; i < UIP_CONNS; i++) 64 | { 65 | uip_periodic(i); 66 | /* If the above function invocation resulted in data that 67 | should be sent out on the network, the global variable 68 | uip_len is set to a value > 0. */ 69 | if(uip_len > 0) 70 | { 71 | slipdev_send(); 72 | } 73 | } 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /src/clock-arch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * $Id: clock-arch.h,v 1.2 2006/06/12 08:00:31 adam Exp $ 32 | */ 33 | 34 | #ifndef __CLOCK_ARCH_H__ 35 | #define __CLOCK_ARCH_H__ 36 | 37 | #include 38 | 39 | typedef uint32_t clock_time_t; 40 | #define CLOCK_CONF_SECOND 10 /* 100ms */ 41 | void clock_setup(void); 42 | 43 | #endif /* __CLOCK_ARCH_H__ */ 44 | -------------------------------------------------------------------------------- /src/slipdev.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Adam Dunkels. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote 14 | * products derived from this software without specific prior 15 | * written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack. 30 | * 31 | * 32 | */ 33 | 34 | /** 35 | * \file 36 | * SLIP header file. 37 | * \author Adam Dunkels 38 | */ 39 | 40 | /** 41 | * \addtogroup slip 42 | * @{ 43 | */ 44 | 45 | #ifndef SLIPDEV_H_ 46 | #define SLIPDEV_H_ 47 | 48 | #include "stdint.h" 49 | 50 | void slipdev_init(void); 51 | uint8_t slipdev_send(void); 52 | uint16_t slipdev_poll(void); 53 | 54 | #endif /* SLIPDEV_H_ */ 55 | 56 | /** @} */ 57 | -------------------------------------------------------------------------------- /src/ringbuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | typedef struct 6 | { 7 | uint8_t *buffer; 8 | volatile uint16_t read_ptr; 9 | volatile uint16_t write_ptr; 10 | uint16_t size; 11 | } ringbuffer_t; 12 | 13 | static inline void ringbuffer_init(ringbuffer_t *ring, void *buffer, uint16_t size) 14 | { 15 | ring->buffer = buffer; 16 | ring->read_ptr = 0; 17 | ring->write_ptr = 0; 18 | ring->size = size; 19 | } 20 | 21 | static inline uint16_t ringbuffer_available(ringbuffer_t *ring) 22 | { 23 | if (ring->write_ptr >= ring->read_ptr) 24 | { 25 | return ring->write_ptr - ring->read_ptr; 26 | } 27 | else 28 | { 29 | return ring->size - ring->read_ptr + ring->write_ptr; 30 | } 31 | } 32 | 33 | static inline uint8_t ringbuffer_read_one(ringbuffer_t *ring) 34 | { 35 | uint8_t byte = ring->buffer[ring->read_ptr++]; 36 | ring->read_ptr %= ring->size; 37 | return byte; 38 | } 39 | 40 | static inline void ringbuffer_write_one(ringbuffer_t *ring, uint8_t byte) 41 | { 42 | ring->buffer[ring->write_ptr++] = byte; 43 | ring->write_ptr %= ring->size; 44 | } 45 | 46 | static inline void ringbuffer_write(ringbuffer_t *ring, const void *data, uint16_t len) 47 | { 48 | if (ring->size - ring->write_ptr < len) 49 | { 50 | const uint8_t *data8 = data; 51 | if (len > ring->size) 52 | { 53 | data8 += len - ring->size; 54 | len = ring->size; 55 | } 56 | 57 | memcpy(&ring->buffer[ring->write_ptr], data8, ring->size - ring->write_ptr); 58 | data8 += ring->size - ring->write_ptr; 59 | len -= ring->size - ring->write_ptr; 60 | ring->write_ptr = 0; 61 | 62 | memcpy(&ring->buffer[ring->write_ptr], data8, len); 63 | ring->write_ptr += len; 64 | } 65 | else 66 | { 67 | memcpy(&ring->buffer[ring->write_ptr], data, len); 68 | ring->write_ptr += len; 69 | } 70 | 71 | ring->write_ptr %= ring->size; 72 | } 73 | 74 | static inline void ringbuffer_advance_read(ringbuffer_t *ring, uint16_t len) 75 | { 76 | if (len > ring->size) 77 | { 78 | len -= ring->size; 79 | } 80 | 81 | ring->read_ptr += len; 82 | ring->read_ptr %= ring->size; 83 | } 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fxIP 2 | ### TCP/IP stack and IRC client for Casio fx-9860/9750 calculators 3 | 4 | 5 |   6 | 7 | ![Screenshot of ping](https://screenshot.tbspace.de/uwaontfeqlk.png) 8 | 9 | [YouTube video of fxIP's IRC client, connecting to irc.libera.chat](https://www.youtube.com/watch?v=afkrucsMMrc) 10 | [YouTube video of fxTerm, a simple RS232 terminal application](https://www.youtube.com/watch?v=epFX8K0dhdY) 11 | 12 | fxIP is a port of [uIP 1.0](https://github.com/adamdunkels/uip) to Casio fx-9750/fx-9860 calculators. 13 | It (currently) requires calculators with a SuperH SH4a CPU, needs quite a bit of SRAM. 14 | 15 | fxIP connects to IP networks via SLIP encapsulation over the 3-pin 2.5mm 5V serial port/UART. 16 | By default, it connects to irc.libera.chat (without SSL). 17 | 18 | [TobleMiner](https://github.com/TobleMiner) wrote the SCIF UART driver, the ringbuffer implementation, the object-log storage, 19 | which is used to store IRC and log messages for display and fixed issues with endianess on SuperH and the SLIP encapsulation. 20 | 21 | ### Network setup (needs root) 22 | ``` 23 | slattach -s 115200 -p slip -v -d -L /dev/ttyUSB0 24 | ip addr add 10.10.10.1/24 dev sl0 25 | ip link set mtu 576 dev sl0 26 | ip link set sl0 up 27 | iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 28 | echo "1" > /proc/sys/net/ipv4/ip_forward 29 | ``` 30 | 31 | ### Building Add-In 32 | Requires [fxsdk](https://gitea.planet-casio.com/Lephenixnoir/fxsdk) and gint to build. 33 | gint needs to be patched using gint.patch before building. 34 | ``` 35 | touch src/main.c && make clean && fxsdk build-fx && cp -f Fxip.g1a ~/Exchange/Test/ 36 | ``` 37 | 38 | 39 | ### Credits 40 | fxIP uses the following fantastic projects: 41 | [fxsdk](https://gitea.planet-casio.com/Lephenixnoir/fxsdk) by [Lephenixnoir](https://gitea.planet-casio.com/Lephenixnoir) 42 | [c-object-log](https://github.com/TobleMiner/c-object-log) by [TobleMiner](https://github.com/TobleMiner) 43 | [uIP 1.0](https://github.com/adamdunkels/uip) by [Adam Dunkels](https://github.com/adamdunkels) 44 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | #include "scif.h" 8 | #include "ui.h" 9 | #include "log.h" 10 | #include "network.h" 11 | #include "clock-arch.h" 12 | #include "hayes.h" 13 | #include "uip/irc.h" 14 | 15 | int __Serial_Open (unsigned char *mode); 16 | int __Serial_Close (int mode); 17 | 18 | static int casioos_Serial_Init() 19 | { 20 | unsigned char settings[5]={0,9,0,0,0}; 21 | __Serial_Open(settings); 22 | return 0; 23 | } 24 | static int casioos_Serial_Close() 25 | { 26 | __Serial_Close(1); 27 | return 0; 28 | } 29 | 30 | //uint8_t atdt_call_buffer[128]; 31 | 32 | int main(void) 33 | { 34 | gint_world_switch(GINT_CALL(casioos_Serial_Init)); 35 | scif_init(); 36 | 37 | ui_init(); 38 | fxip_log(""); 39 | fxip_log("fxIP, build date:"); 40 | fxip_log(&__TIMESTAMP__[4]); 41 | fxip_log("manawyrm & TobleMiner"); 42 | 43 | clock_setup(); 44 | 45 | /*while (hayes_send_and_read("ATI3", atdt_call_buffer, sizeof(atdt_call_buffer)) == 0) 46 | { 47 | uint32_t start = clock_time(); 48 | while (start + 1 > clock_time()); 49 | } 50 | fxip_log("read 1:"); 51 | fxip_log(atdt_call_buffer); 52 | 53 | fxip_log("Calling **2"); 54 | 55 | scif_read_flush(); 56 | hayes_send("ATDT **2"); 57 | 58 | while (true) 59 | { 60 | hayes_read(atdt_call_buffer, sizeof(atdt_call_buffer), 0, 1); 61 | fxip_log("read 2:"); 62 | fxip_log(atdt_call_buffer); 63 | }*/ 64 | 65 | network_init(); 66 | 67 | uint32_t last_clock_time = 0; 68 | while (true) 69 | { 70 | network_poll(); 71 | 72 | if (ui_handle_keyboard()) 73 | { 74 | // Exit 75 | if (!messagelength) 76 | { 77 | memcpy(messagebuffer, "QUIT", 4); 78 | messagelength = 4; 79 | 80 | uint32_t now = clock_time(); 81 | while ((clock_time() - now < 50) && messagelength) 82 | { 83 | network_poll(); 84 | } 85 | } 86 | 87 | gint_world_switch(GINT_CALL(casioos_Serial_Close)); 88 | return 1; 89 | } 90 | 91 | uint32_t now = clock_time(); 92 | if (last_clock_time != now && now % 5 == 0) 93 | { 94 | ui_cursor_blink(); 95 | ui_update(); 96 | last_clock_time = now; 97 | } 98 | } 99 | 100 | return 1; 101 | } -------------------------------------------------------------------------------- /src/fxlibc/strstr_base.c: -------------------------------------------------------------------------------- 1 | #include "string_p.h" 2 | #include 3 | #include 4 | #include 5 | 6 | /* Quadratic-time brute-force algorithm. */ 7 | static char *strstr_bruteforce(char const *haystack, char const *needle, 8 | bool ignore_case) 9 | { 10 | size_t len_needle = strlen(needle); 11 | 12 | while(*haystack) { 13 | int diff = ignore_case 14 | ? strncasecmp(haystack, needle, len_needle) 15 | : strncmp(haystack, needle, len_needle); 16 | 17 | if(!diff) return (char *)haystack; 18 | haystack++; 19 | } 20 | 21 | return NULL; 22 | } 23 | 24 | /* Linear-time Knuth-Morris-Pratt algorithm. */ 25 | static char *strstr_kmp(char const *haystack, char const *needle, int16_t *T, 26 | bool ignore_case) 27 | { 28 | /* Be careful, this macro has double evaluation */ 29 | #define equal(c1, c2) \ 30 | (ignore_case ? tolower(c1) == tolower(c2) : (c1) == (c2)) 31 | 32 | /* Build the failure function */ 33 | 34 | T[0] = -1; 35 | int cnd = 0; 36 | 37 | for(int pos = 1; needle[pos]; pos++, cnd++) { 38 | if(equal(needle[pos], needle[cnd])) { 39 | T[pos] = T[cnd]; 40 | } 41 | else { 42 | T[pos] = cnd; 43 | while(cnd >= 0 && !equal(needle[pos], needle[cnd])) 44 | cnd = T[cnd]; 45 | } 46 | } 47 | 48 | /* Perform linear-time matching */ 49 | 50 | int i=0, pos=0; 51 | while(haystack[i]) { 52 | if(equal(needle[pos], haystack[i])) { 53 | pos++; 54 | i++; 55 | 56 | if(!needle[pos]) return (char *)haystack + i - pos; 57 | } 58 | else { 59 | pos = T[pos]; 60 | if(pos < 0) { 61 | pos++; 62 | i++; 63 | } 64 | } 65 | } 66 | 67 | return NULL; 68 | } 69 | 70 | char *__strstr_base(char const *haystack, char const *needle, 71 | bool ignore_case) 72 | { 73 | size_t len_needle = strlen(needle); 74 | int16_t *T = NULL; 75 | 76 | /* 77 | ** Don't use the KMP algorithm for huge needles (> 64 kiB) as indexes 78 | ** might not fit in an int16_t. (In any case, if you need to search for 79 | ** such a huge pattern, don't use strstr.) 80 | */ 81 | if(len_needle < INT16_MAX) { 82 | T = malloc(len_needle * sizeof *T); 83 | } 84 | 85 | /* Fall back to bruteforce if allocation fails */ 86 | if(T) { 87 | char *match = strstr_kmp(haystack, needle, T, ignore_case); 88 | free(T); 89 | return match; 90 | } 91 | else { 92 | return strstr_bruteforce(haystack, needle, ignore_case); 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /src/log.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "log.h" 7 | #include "util.h" 8 | #include "ui.h" 9 | 10 | void fxip_log(const char *msg) 11 | { 12 | ui_write_log(PAGE_LOGS, 0, 0, msg, strlen(msg)); 13 | ui_update_logs(); 14 | } 15 | 16 | void uip_log(char *msg) 17 | { 18 | fxip_log(msg); 19 | } 20 | 21 | char printf_buffer[128]; 22 | void fxip_printf(const char * format, ...) 23 | { 24 | va_list args; 25 | va_start (args, format); 26 | vsnprintf (printf_buffer, sizeof(printf_buffer), format, args); 27 | fxip_log (printf_buffer); 28 | va_end (args); 29 | } 30 | 31 | 32 | void fxip_print_hexdump(const void *addr, uint16_t size) 33 | { 34 | uint16_t printed = 0; 35 | uint16_t bufferoffset = 0; 36 | uint16_t i; 37 | 38 | memset(printf_buffer, 0x00, sizeof(printf_buffer)); 39 | 40 | const unsigned char* pc = addr; 41 | for (i=0; i> 4) & 0xf; 45 | g += g >= 10 ? 'a'-10 : '0'; 46 | printf_buffer[bufferoffset++] = g; 47 | printed++; 48 | 49 | g = *(pc+i) & 0xf; 50 | g += g >= 10 ? 'a'-10 : '0'; 51 | printf_buffer[bufferoffset++] = g; 52 | printed++; 53 | if (printed % 16 == 0) 54 | { 55 | fxip_log (printf_buffer); 56 | bufferoffset = 0; 57 | memset(printf_buffer, 0x00, sizeof(printf_buffer)); 58 | } 59 | else if (printed % 4 == 0) printf_buffer[bufferoffset++] = ' '; 60 | } 61 | fxip_log (printf_buffer); 62 | } 63 | 64 | void rom_putchar_uart(char asdf) 65 | { 66 | scif_write(&asdf, 1); 67 | } 68 | void fxip_serial_hexdump(const void *addr, uint16_t size) 69 | { 70 | uint16_t printed = 0; 71 | uint16_t i; 72 | const unsigned char* pc = addr; 73 | for (i=0; i> 4) & 0xf; 77 | g += g >= 10 ? 'a'-10 : '0'; 78 | rom_putchar_uart(g); 79 | printed++; 80 | g = *(pc+i) & 0xf; 81 | g += g >= 10 ? 'a'-10 : '0'; 82 | rom_putchar_uart(g); 83 | printed++; 84 | if (printed % 32 == 0) rom_putchar_uart('\n'); 85 | else if (printed % 4 == 0) rom_putchar_uart(' '); 86 | } 87 | } 88 | void serial_printf(const char * format, ...) 89 | { 90 | va_list args; 91 | va_start (args, format); 92 | vsnprintf (printf_buffer, sizeof(printf_buffer), format, args); 93 | scif_write(printf_buffer, strlen(printf_buffer)); 94 | va_end (args); 95 | } 96 | -------------------------------------------------------------------------------- /src/clock-arch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * $Id: clock-arch.c,v 1.2 2006/06/12 08:00:31 adam Exp $ 32 | */ 33 | 34 | /** 35 | * \file 36 | * Implementation of architecture-specific clock functionality 37 | * \author 38 | * Adam Dunkels 39 | */ 40 | 41 | #include "clock-arch.h" 42 | #include 43 | 44 | static volatile uint32_t ticks = 0; 45 | static int timer; 46 | /*---------------------------------------------------------------------------*/ 47 | clock_time_t 48 | clock_time(void) 49 | { 50 | return ticks; 51 | } 52 | 53 | static int clock_tick_callback() 54 | { 55 | ticks++; 56 | return TIMER_CONTINUE; 57 | } 58 | 59 | void clock_setup(void) 60 | { 61 | ticks = 0; 62 | timer = timer_configure(TIMER_ANY, 100000 /* 100ms */, GINT_CALL(clock_tick_callback)); 63 | timer_start(timer); 64 | } 65 | /*---------------------------------------------------------------------------*/ 66 | -------------------------------------------------------------------------------- /src/uip/uip-neighbor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * $Id: uip-neighbor.h,v 1.2 2006/06/12 08:00:30 adam Exp $ 32 | */ 33 | 34 | /** 35 | * \file 36 | * Header file for database of link-local neighbors, used by 37 | * IPv6 code and to be used by future ARP code. 38 | * \author 39 | * Adam Dunkels 40 | */ 41 | 42 | #ifndef __UIP_NEIGHBOR_H__ 43 | #define __UIP_NEIGHBOR_H__ 44 | 45 | #include "uip.h" 46 | 47 | struct uip_neighbor_addr { 48 | #if UIP_NEIGHBOR_CONF_ADDRTYPE 49 | UIP_NEIGHBOR_CONF_ADDRTYPE addr; 50 | #else 51 | struct uip_eth_addr addr; 52 | #endif 53 | }; 54 | 55 | void uip_neighbor_init(void); 56 | void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr); 57 | void uip_neighbor_update(uip_ipaddr_t ipaddr); 58 | struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr); 59 | void uip_neighbor_periodic(void); 60 | 61 | #endif /* __UIP-NEIGHBOR_H__ */ 62 | -------------------------------------------------------------------------------- /src/uip/uiplib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004, Adam Dunkels and the Swedish Institute of 3 | * Computer Science. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. The name of the author may not be used to endorse or promote 15 | * products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 24 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * This file is part of the uIP TCP/IP stack 31 | * 32 | * $Id: uiplib.c,v 1.2 2006/06/12 08:00:31 adam Exp $ 33 | * 34 | */ 35 | 36 | 37 | #include "uip.h" 38 | #include "uiplib.h" 39 | 40 | 41 | /*-----------------------------------------------------------------------------------*/ 42 | unsigned char 43 | uiplib_ipaddrconv(char *addrstr, unsigned char *ipaddr) 44 | { 45 | unsigned char tmp; 46 | char c; 47 | unsigned char i, j; 48 | 49 | tmp = 0; 50 | 51 | for(i = 0; i < 4; ++i) { 52 | j = 0; 53 | do { 54 | c = *addrstr; 55 | ++j; 56 | if(j > 4) { 57 | return 0; 58 | } 59 | if(c == '.' || c == 0) { 60 | *ipaddr = tmp; 61 | ++ipaddr; 62 | tmp = 0; 63 | } else if(c >= '0' && c <= '9') { 64 | tmp = (tmp * 10) + (c - '0'); 65 | } else { 66 | return 0; 67 | } 68 | ++addrstr; 69 | } while(c != '.' && c != 0); 70 | } 71 | return 1; 72 | } 73 | 74 | /*-----------------------------------------------------------------------------------*/ 75 | -------------------------------------------------------------------------------- /src/uip/uiplib.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * Various uIP library functions. 4 | * \author 5 | * Adam Dunkels 6 | * 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2002, Adam Dunkels. 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without 14 | * modification, are permitted provided that the following conditions 15 | * are met: 16 | * 1. Redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer. 18 | * 2. Redistributions in binary form must reproduce the above 19 | * copyright notice, this list of conditions and the following 20 | * disclaimer in the documentation and/or other materials provided 21 | * with the distribution. 22 | * 3. The name of the author may not be used to endorse or promote 23 | * products derived from this software without specific prior 24 | * written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 27 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 30 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 32 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 34 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | * 38 | * This file is part of the uIP TCP/IP stack 39 | * 40 | * $Id: uiplib.h,v 1.1 2006/06/07 09:15:19 adam Exp $ 41 | * 42 | */ 43 | #ifndef __UIPLIB_H__ 44 | #define __UIPLIB_H__ 45 | 46 | /** 47 | * \addtogroup uipconvfunc 48 | * @{ 49 | */ 50 | 51 | /** 52 | * Convert a textual representation of an IP address to a numerical representation. 53 | * 54 | * This function takes a textual representation of an IP address in 55 | * the form a.b.c.d and converts it into a 4-byte array that can be 56 | * used by other uIP functions. 57 | * 58 | * \param addrstr A pointer to a string containing the IP address in 59 | * textual form. 60 | * 61 | * \param addr A pointer to a 4-byte array that will be filled in with 62 | * the numerical representation of the address. 63 | * 64 | * \retval 0 If the IP address could not be parsed. 65 | * \retval Non-zero If the IP address was parsed. 66 | */ 67 | unsigned char uiplib_ipaddrconv(char *addrstr, unsigned char *addr); 68 | 69 | /** @} */ 70 | 71 | #endif /* __UIPLIB_H__ */ 72 | -------------------------------------------------------------------------------- /src/fxlibc/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef __CTYPE_H__ 2 | # define __CTYPE_H__ 3 | 4 | /* 5 | ** Character classification functions. These are all implemented as sets of 6 | ** comparisons. There is an approach with a 128-byte table, but it takes more 7 | ** space; in fact, every function but isalnum, ispunct and isxdigit needs less 8 | ** code to compare than to perform the lookup. Additionally, users won't need 9 | ** the whole table for a single call to isspace(). 10 | */ 11 | extern int isalnum(int c); 12 | extern int isalpha(int c); 13 | extern int isblank(int c); 14 | extern int iscntrl(int c); 15 | extern int isdigit(int c); 16 | extern int isgraph(int c); 17 | extern int islower(int c); 18 | extern int isprint(int c); 19 | extern int ispunct(int c); 20 | extern int isspace(int c); 21 | extern int isupper(int c); 22 | extern int isxdigit(int c); 23 | 24 | /* Case conversion functions */ 25 | extern int tolower(int c); 26 | extern int toupper(int c); 27 | 28 | /* 29 | ** Macro versions; these functions are very fast so it's worth it to inline 30 | ** them rather than perform a function call as expensive as the test. These are 31 | ** valid in the "C" locale, the only one supported by this library. 32 | */ 33 | 34 | #define isalnum(c) ({ \ 35 | int __c0 = (c); \ 36 | isalpha(__c0) || isdigit(__c0); \ 37 | }) 38 | 39 | #define isalpha(c) ({ \ 40 | int __c = (c) | 0x20; \ 41 | (__c >= 'a') && (__c <= 'z'); \ 42 | }) 43 | 44 | #define isblank(c) ({ \ 45 | int __c = (c); \ 46 | (__c == 9) || (__c == 32); \ 47 | }) 48 | 49 | #define iscntrl(c) ({ \ 50 | int __c = (c); \ 51 | (__c < 32) || (__c >= 0x7f); \ 52 | }) 53 | 54 | #define isdigit(c) ({ \ 55 | int __c = (c); \ 56 | (__c >= '0') && (__c <= '9'); \ 57 | }) 58 | 59 | #define isgraph(c) ({ \ 60 | int __c = (c); \ 61 | (__c >= 33) && (__c < 0x7f); \ 62 | }) 63 | 64 | #define islower(c) ({ \ 65 | int __c = (c); \ 66 | (__c >= 'a') && (__c <= 'z'); \ 67 | }) 68 | 69 | #define isprint(c) ({ \ 70 | int __c = (c); \ 71 | (__c >= 32) && (__c < 0x7f); \ 72 | }) 73 | 74 | #define ispunct(c) ({ \ 75 | int __c = (c); \ 76 | (__c >= 33 && __c <= 47) || (__c >= 58 && __c <= 64) || \ 77 | (__c >= 91 && __c <= 96) || (__c >= 123 && __c <= 126); \ 78 | }) 79 | 80 | #define isspace(c) ({ \ 81 | int __c = (c); \ 82 | (__c >= 9 && __c <= 13) || (__c == 32); \ 83 | }) 84 | 85 | #define isupper(c) ({ \ 86 | int __c = (c); \ 87 | (__c >= 'A') && (__c <= 'Z'); \ 88 | }) 89 | 90 | #define isxdigit(c) ({ \ 91 | int __c = (c); \ 92 | int __c20 = __c | 0x20; \ 93 | (__c >= '0' && __c <= '9') || (__c20 >= 'a' && __c20 <= 'f'); \ 94 | }) 95 | 96 | #define tolower(c) ({ \ 97 | int __c0 = (c); \ 98 | isupper(__c0) ? (__c0 | 0x20) : __c0; \ 99 | }) 100 | 101 | #define toupper(c) ({ \ 102 | int __c0 = (c); \ 103 | islower(__c0) ? (__c0 & 0xdf) : __c0; \ 104 | }) 105 | 106 | #endif /*__CTYPE_H__*/ 107 | -------------------------------------------------------------------------------- /src/uip/lc-switch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004-2005, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: lc-switch.h,v 1.2 2006/06/12 08:00:30 adam Exp $ 34 | */ 35 | 36 | /** 37 | * \addtogroup lc 38 | * @{ 39 | */ 40 | 41 | /** 42 | * \file 43 | * Implementation of local continuations based on switch() statment 44 | * \author Adam Dunkels 45 | * 46 | * This implementation of local continuations uses the C switch() 47 | * statement to resume execution of a function somewhere inside the 48 | * function's body. The implementation is based on the fact that 49 | * switch() statements are able to jump directly into the bodies of 50 | * control structures such as if() or while() statmenets. 51 | * 52 | * This implementation borrows heavily from Simon Tatham's coroutines 53 | * implementation in C: 54 | * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html 55 | */ 56 | 57 | #ifndef __LC_SWITCH_H__ 58 | #define __LC_SWTICH_H__ 59 | 60 | /* WARNING! lc implementation using switch() does not work if an 61 | LC_SET() is done within another switch() statement! */ 62 | 63 | /** \hideinitializer */ 64 | typedef unsigned short lc_t; 65 | 66 | #define LC_INIT(s) s = 0; 67 | 68 | #define LC_RESUME(s) switch(s) { case 0: 69 | 70 | #define LC_SET(s) s = __LINE__; case __LINE__: 71 | 72 | #define LC_END(s) } 73 | 74 | #endif /* __LC_SWITCH_H__ */ 75 | 76 | /** @} */ 77 | -------------------------------------------------------------------------------- /gint.patch: -------------------------------------------------------------------------------- 1 | diff -Naur gint-orig/fx9860g.ld gint-mod/fx9860g.ld 2 | --- gint-orig/fx9860g.ld 2021-05-12 09:16:14.000000000 +0200 3 | +++ gint-mod/fx9860g.ld 2021-07-13 21:46:59.045357371 +0200 4 | @@ -25,7 +25,7 @@ 5 | 0x1100 bytes near the end of the user RAM, which is larger; the 6k 6 | left for the user are honored in both cases. Unused memory from the 7 | exposed 6k and non-exposed memory is available through malloc(). */ 8 | - ram (rw): o = 0x08100200, l = 6k 9 | + ram (rw): o = 0x08100200, l = 30k 10 | 11 | /* This region represents the first block of user RAM. Linker arranges 12 | sections as if linked to address 0, then gint's runtime determines 13 | diff -Naur gint-orig/include/gint/intc.h gint-mod/include/gint/intc.h 14 | --- gint-orig/include/gint/intc.h 2021-05-12 09:16:14.000000000 +0200 15 | +++ gint-mod/include/gint/intc.h 2021-07-13 21:46:59.052024044 +0200 16 | @@ -36,6 +36,8 @@ 17 | INTC_DMA_DEI4, 18 | INTC_DMA_DEI5, 19 | INTC_DMA_DADERR, 20 | + /* Serial Communication Interface with FIFO (SCIF0) */ 21 | + INTC_SCIF0, 22 | /* Real-Time Clock [RTC]; a single IPR covers all 3 interrupts */ 23 | INTC_RTC_ATI, 24 | INTC_RTC_PRI, 25 | diff -Naur gint-orig/src/intc/intc.c gint-mod/src/intc/intc.c 26 | --- gint-orig/src/intc/intc.c 2021-05-12 09:16:14.000000000 +0200 27 | +++ gint-mod/src/intc/intc.c 2021-07-13 21:46:59.058690718 +0200 28 | @@ -57,6 +57,8 @@ 29 | { IPRF, 0x0f00, IMR5, 0x10, _ }, 30 | { IPRF, 0x0f00, IMR5, 0x20, _ }, 31 | { IPRF, 0x0f00, IMR5, 0x40, _ }, 32 | + /* SCIF */ 33 | + { IPRG, 0xf000, IMR5, 0x01, _ }, 34 | /* RTC */ 35 | { IPRK, 0xf000, IMR10, 0x04, IPRA, 0x000f }, 36 | { IPRK, 0xf000, IMR10, 0x02, IPRA, 0x000f }, 37 | diff -Naur gint-orig/src/kernel/syscalls.S gint-mod/src/kernel/syscalls.S 38 | --- gint-orig/src/kernel/syscalls.S 2021-05-12 09:16:14.000000000 +0200 39 | +++ gint-mod/src/kernel/syscalls.S 2021-07-13 21:46:59.058690718 +0200 40 | @@ -40,6 +40,18 @@ 41 | .global ___GetVRAMAddress 42 | .global ___ConfigureStatusArea 43 | 44 | +.global ___Serial_Open 45 | +.global ___Serial_Close 46 | +.global ___Serial_ReadByte 47 | +.global ___Serial_ReadBytes 48 | +.global ___Serial_WriteByte 49 | +.global ___Serial_WriteBytes 50 | +.global ___Serial_GetRxBufferSize 51 | +.global ___Serial_GetTxBufferFreeCapacity 52 | +.global ___Serial_ClearReceiveBuffer 53 | +.global ___Serial_ClearTransmitBuffer 54 | +.global ___OS_InnerWait_ms 55 | + 56 | #define syscall_(id, syscall_table) \ 57 | mov.l syscall_table, r2 ;\ 58 | mov.l 1f, r0 ;\ 59 | @@ -103,6 +115,32 @@ 60 | ___GetVRAMAddress: 61 | syscall(0x135) 62 | 63 | + 64 | +___Serial_Open: 65 | + syscall(0x418) 66 | +___Serial_Close: 67 | + syscall(0x419) 68 | +___Serial_ReadByte: 69 | + syscall(0x040C) 70 | +___Serial_ReadBytes: 71 | + syscall(0x040D) 72 | +___Serial_WriteByte: 73 | + syscall(0x040E) 74 | +___Serial_WriteBytes: 75 | + syscall(0x040F) 76 | +___Serial_GetRxBufferSize: 77 | + syscall(0x0411) 78 | +___Serial_GetTxBufferFreeCapacity: 79 | + syscall(0x0412) 80 | +___Serial_ClearReceiveBuffer: 81 | + syscall(0x0413) 82 | +___Serial_ClearTransmitBuffer: 83 | + syscall(0x0414) 84 | + 85 | +___OS_InnerWait_ms: 86 | + syscall(0x0420) 87 | + 88 | + 89 | syscall_table: 90 | .long 0x80010070 91 | -------------------------------------------------------------------------------- /src/uip/timer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \defgroup timer Timer library 3 | * 4 | * The timer library provides functions for setting, resetting and 5 | * restarting timers, and for checking if a timer has expired. An 6 | * application must "manually" check if its timers have expired; this 7 | * is not done automatically. 8 | * 9 | * A timer is declared as a \c struct \c timer and all access to the 10 | * timer is made by a pointer to the declared timer. 11 | * 12 | * \note The timer library uses the \ref clock "Clock library" to 13 | * measure time. Intervals should be specified in the format used by 14 | * the clock library. 15 | * 16 | * @{ 17 | */ 18 | 19 | 20 | /** 21 | * \file 22 | * Timer library header file. 23 | * \author 24 | * Adam Dunkels 25 | */ 26 | 27 | /* 28 | * Copyright (c) 2004, Swedish Institute of Computer Science. 29 | * All rights reserved. 30 | * 31 | * Redistribution and use in source and binary forms, with or without 32 | * modification, are permitted provided that the following conditions 33 | * are met: 34 | * 1. Redistributions of source code must retain the above copyright 35 | * notice, this list of conditions and the following disclaimer. 36 | * 2. Redistributions in binary form must reproduce the above copyright 37 | * notice, this list of conditions and the following disclaimer in the 38 | * documentation and/or other materials provided with the distribution. 39 | * 3. Neither the name of the Institute nor the names of its contributors 40 | * may be used to endorse or promote products derived from this software 41 | * without specific prior written permission. 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 44 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 47 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 | * SUCH DAMAGE. 54 | * 55 | * This file is part of the uIP TCP/IP stack 56 | * 57 | * Author: Adam Dunkels 58 | * 59 | * $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $ 60 | */ 61 | #ifndef __TIMER_H__ 62 | #define __TIMER_H__ 63 | 64 | #include "clock.h" 65 | 66 | /** 67 | * A timer. 68 | * 69 | * This structure is used for declaring a timer. The timer must be set 70 | * with timer_set() before it can be used. 71 | * 72 | * \hideinitializer 73 | */ 74 | struct timer { 75 | clock_time_t start; 76 | clock_time_t interval; 77 | }; 78 | 79 | void timer_set(struct timer *t, clock_time_t interval); 80 | void timer_reset(struct timer *t); 81 | void timer_restart(struct timer *t); 82 | int timer_expired(struct timer *t); 83 | 84 | #endif /* __TIMER_H__ */ 85 | 86 | /** @} */ 87 | -------------------------------------------------------------------------------- /src/uip/clock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \defgroup clock Clock interface 3 | * 4 | * The clock interface is the interface between the \ref timer "timer library" 5 | * and the platform specific clock functionality. The clock 6 | * interface must be implemented for each platform that uses the \ref 7 | * timer "timer library". 8 | * 9 | * The clock interface does only one this: it measures time. The clock 10 | * interface provides a macro, CLOCK_SECOND, which corresponds to one 11 | * second of system time. 12 | * 13 | * \sa \ref timer "Timer library" 14 | * 15 | * @{ 16 | */ 17 | 18 | /* 19 | * Copyright (c) 2004, Swedish Institute of Computer Science. 20 | * All rights reserved. 21 | * 22 | * Redistribution and use in source and binary forms, with or without 23 | * modification, are permitted provided that the following conditions 24 | * are met: 25 | * 1. Redistributions of source code must retain the above copyright 26 | * notice, this list of conditions and the following disclaimer. 27 | * 2. Redistributions in binary form must reproduce the above copyright 28 | * notice, this list of conditions and the following disclaimer in the 29 | * documentation and/or other materials provided with the distribution. 30 | * 3. Neither the name of the Institute nor the names of its contributors 31 | * may be used to endorse or promote products derived from this software 32 | * without specific prior written permission. 33 | * 34 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 35 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 38 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 | * SUCH DAMAGE. 45 | * 46 | * This file is part of the uIP TCP/IP stack 47 | * 48 | * Author: Adam Dunkels 49 | * 50 | * $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $ 51 | */ 52 | #ifndef __CLOCK_H__ 53 | #define __CLOCK_H__ 54 | 55 | #include "clock-arch.h" 56 | 57 | /** 58 | * Initialize the clock library. 59 | * 60 | * This function initializes the clock library and should be called 61 | * from the main() function of the system. 62 | * 63 | */ 64 | void clock_init(void); 65 | 66 | /** 67 | * Get the current clock time. 68 | * 69 | * This function returns the current system clock time. 70 | * 71 | * \return The current clock time, measured in system ticks. 72 | */ 73 | clock_time_t clock_time(void); 74 | 75 | /** 76 | * A second, measured in system clock time. 77 | * 78 | * \hideinitializer 79 | */ 80 | #ifdef CLOCK_CONF_SECOND 81 | #define CLOCK_SECOND CLOCK_CONF_SECOND 82 | #else 83 | #define CLOCK_SECOND (clock_time_t)32 84 | #endif 85 | 86 | #endif /* __CLOCK_H__ */ 87 | 88 | /** @} */ 89 | -------------------------------------------------------------------------------- /src/uip/lc-addrlabels.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004-2005, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: lc-addrlabels.h,v 1.3 2006/06/12 08:00:30 adam Exp $ 34 | */ 35 | 36 | /** 37 | * \addtogroup lc 38 | * @{ 39 | */ 40 | 41 | /** 42 | * \file 43 | * Implementation of local continuations based on the "Labels as 44 | * values" feature of gcc 45 | * \author 46 | * Adam Dunkels 47 | * 48 | * This implementation of local continuations is based on a special 49 | * feature of the GCC C compiler called "labels as values". This 50 | * feature allows assigning pointers with the address of the code 51 | * corresponding to a particular C label. 52 | * 53 | * For more information, see the GCC documentation: 54 | * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html 55 | * 56 | * Thanks to dividuum for finding the nice local scope label 57 | * implementation. 58 | */ 59 | 60 | #ifndef __LC_ADDRLABELS_H__ 61 | #define __LC_ADDRLABELS_H__ 62 | 63 | /** \hideinitializer */ 64 | typedef void * lc_t; 65 | 66 | #define LC_INIT(s) s = NULL 67 | 68 | 69 | #define LC_RESUME(s) \ 70 | do { \ 71 | if(s != NULL) { \ 72 | goto *s; \ 73 | } \ 74 | } while(0) 75 | 76 | #define LC_SET(s) \ 77 | do { ({ __label__ resume; resume: (s) = &&resume; }); }while(0) 78 | 79 | #define LC_END(s) 80 | 81 | #endif /* __LC_ADDRLABELS_H__ */ 82 | 83 | /** @} */ 84 | -------------------------------------------------------------------------------- /project.cfg: -------------------------------------------------------------------------------- 1 | #--- 2 | # fxSDK project configuration file for Fxip 3 | #--- 4 | 5 | # Project name, should be at most 8 bytes long. 6 | # (You can also specify NAME_G1A or NAME_G3A to override individually.) 7 | NAME := Fxip 8 | 9 | # Internal name, should be '@' followed by at most 7 uppercase letters. 10 | # WARNING: If this convention is not followed, the add-in might not appear in 11 | # the main menu of the calculator! 12 | INTERNAL := @FXIP 13 | 14 | # Output file name. The default is to take , replace spaces with dashes, 15 | # and add .g1a (or .g3a). You can specify a different folder if you want. 16 | TARGET_FX := 17 | TARGET_CG := 18 | 19 | # fx-9860G icon location 20 | ICON_FX = assets-fx/icon.png 21 | # fx-CG 50 icon locations 22 | ICON_CG_UNS = assets-cg/icon-uns.png 23 | ICON_CG_SEL = assets-cg/icon-sel.png 24 | 25 | #--- 26 | # Toolchain selection 27 | #--- 28 | 29 | # Toolchain for fx9860g. Please see also CFLAGS_FX below. 30 | TOOLCHAIN_FX := sh-elf 31 | 32 | # Toolchain for fxcg50. Please see also CFLAGS_CG below. 33 | TOOLCHAIN_CG := sh-elf 34 | 35 | #--- 36 | # Compiler flags 37 | #--- 38 | 39 | # Base compiler flags for the fxSDK, you usually want to keep these. 40 | CFLAGS := -mb -ffreestanding -nostdlib -fstrict-volatile-bitfields -fcommon 41 | 42 | # Platform-specific compiler flags. 43 | # <> If you are using sh3eb-elf, use -m3. (You can do this on both FX and CG.) 44 | # <> If you are using sh4eb-elf, use -m4-nofpu. (Not ideal on FX but works.) 45 | # <> If you are using sh4eb-nofpu-elf, then your compiler will likely use the 46 | # FPU and cause problems on the calculator. Consider another configuration. 47 | # <> If you are using an sh-elf with several targets, specify whichever you 48 | # support. I recommend -m3 on FX and -m4-nofpu on CG. 49 | # Please see also TOOLCHAIN_FX and TOOLCHAIN_CG above. 50 | CFLAGS_FX := -D FX9860G -D TARGET_FX9860G -m4-nofpu 51 | CFLAGS_CG := -D FXCG50 -D TARGET_FXCG50 -m4-nofpu 52 | 53 | # Additional compiler flags, change to your own taste! 54 | CFLAGS += -Wall -Wextra -Wno-missing-field-initializers -O2 55 | 56 | # Include paths. Add one -I option for each folder from which you want to 57 | # be able to include files with #include<>. The Makefile provides a variable 58 | # GCC_INCLUDE_FX/GCC_INCLUDE_CG that represents the default include folder, 59 | # which is useful for some libraries such as OpenLibm. 60 | INCLUDE_FX = -I include -I src 61 | INCLUDE_CG = -I include -I src 62 | 63 | # Libraries. Add one -l option for each library you are using, and also 64 | # suitable -L options if you have library files in custom folders. To use 65 | # fxlib, add libfx.a to the project directory and use "-L . -lfx". 66 | LIBS_FX := 67 | LIBS_CG := 68 | 69 | # Base linker flags for the fxSDK, you usually want to keep these. 70 | LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS_FX) -lgint-fx -lgcc 71 | LDFLAGS_CG := -T fxcg50.ld -lgint-cg $(LIBS_CG) -lgint-cg -lgcc 72 | 73 | # Additional linker flags, if you need any. 74 | LDFLAGS := 75 | 76 | # Additional platform-specific linker flags. 77 | LDFLAGS_FX += -Wl,-Map=build-fx/map 78 | LDFLAGS_CG += -Wl,-Map=build-cg/map 79 | 80 | #--- 81 | # File conversion parameters 82 | #--- 83 | 84 | # Here you can add fxconv options for each converted file, individually. 85 | # The syntax is ".". For example, to specify the parameters for a 86 | # font named "hexa.png", you might write: 87 | # 88 | # FONT.hexa.png = charset:print grid.size:3x5 grid.padding:1 89 | -------------------------------------------------------------------------------- /src/scif.c: -------------------------------------------------------------------------------- 1 | #include "scif.h" 2 | #include "util.h" 3 | #include 4 | #include "ringbuffer.h" 5 | 6 | #define SCIF_BASE 0xA4410000 7 | #define SCIF_SIZE 0x10000 8 | 9 | #define SCSMR(x) MMIO16(SCIF_BASE + SCIF_SIZE * (x) + 0x00) /* Serial mode register */ 10 | #define SCBRR(x) MMIO8 (SCIF_BASE + SCIF_SIZE * (x) + 0x04) /* Bit rate register */ 11 | #define SCSCR(x) MMIO16(SCIF_BASE + SCIF_SIZE * (x) + 0x08) /* Serial control register */ 12 | #define SCFTDR(x) MMIO8 (SCIF_BASE + SCIF_SIZE * (x) + 0x0C) /* Transmit FIFO data register */ 13 | #define SCFSR(x) MMIO16(SCIF_BASE + SCIF_SIZE * (x) + 0x10) /* Serial status register */ 14 | #define SCFRDR(x) MMIO8 (SCIF_BASE + SCIF_SIZE * (x) + 0x14) /* Receive FIFO data register */ 15 | #define SCFCR(x) MMIO16(SCIF_BASE + SCIF_SIZE * (x) + 0x18) /* FIFO control register */ 16 | #define SCFDR(x) MMIO16(SCIF_BASE + SCIF_SIZE * (x) + 0x1C) /* FIFO data count register */ 17 | #define SCLSR(x) MMIO16(SCIF_BASE + SCIF_SIZE * (x) + 0x24) /* Line status register */ 18 | 19 | #define SCSMR0 SCSMR(0) 20 | #define SCBRR0 SCBRR(0) 21 | #define SCSCR0 SCSCR(0) 22 | #define SCFTDR0 SCFTDR(0) 23 | #define SCFSR0 SCFSR(0) 24 | #define SCFRDR0 SCFRDR(0) 25 | #define SCFCR0 SCFCR(0) 26 | #define SCFDR0 SCFDR(0) 27 | #define SCLSR0 SCLSR(0) 28 | 29 | #define SCFSR_TEND BIT(6) 30 | #define SCFSR_TDFE BIT(5) 31 | #define SCFSR_RDF BIT(1) 32 | #define SCFSR_DR BIT(0) 33 | 34 | #define SCFDR_TFDC_MASK BITMASK(12, 8) 35 | #define SCFDR_TFDC_SHIFT 8 36 | #define SCFDR_TFDC ((SCFDR0 & SCFDR_TFDC_MASK) >> SCFDR_TFDC_SHIFT) 37 | 38 | #define SCFDR_RFDC_MASK BITMASK(4, 0) 39 | #define SCFDR_RFDC_SHIFT 0 40 | #define SCFDR_RFDC ((SCFDR0 & SCFDR_RFDC_MASK) >> SCFDR_RFDC_SHIFT) 41 | 42 | #define SCSCR_TIE BIT(7) 43 | #define SCSCR_TE BIT(5) 44 | 45 | #define SCIF_SCIF0_INTEVT 0xC00 46 | 47 | #define RING_BUF_SIZE 2048 48 | uint8_t rx_buffer[RING_BUF_SIZE]; 49 | ringbuffer_t rx_ring; 50 | 51 | uint8_t tx_buffer[RING_BUF_SIZE]; 52 | ringbuffer_t tx_ring; 53 | 54 | void scif_write(const void *data, uint16_t len) 55 | { 56 | while ((RING_BUF_SIZE - ringbuffer_available(&tx_ring)) < len); 57 | ringbuffer_write(&tx_ring, data, len); 58 | // enable transmit interrupt 59 | SCSCR0 |= SCSCR_TIE; 60 | } 61 | 62 | int scif_read() 63 | { 64 | if (ringbuffer_available(&rx_ring)) 65 | { 66 | return ringbuffer_read_one(&rx_ring); 67 | } 68 | return -1; 69 | } 70 | 71 | int scif_read_flush() 72 | { 73 | while (scif_read() != -1); 74 | } 75 | 76 | static void scif_interrupt() 77 | { 78 | // fill TX FIFO 79 | while (SCFDR_TFDC < 16 && ringbuffer_available(&tx_ring)) 80 | { 81 | SCFTDR0 = ringbuffer_read_one(&tx_ring); 82 | } 83 | if (!ringbuffer_available(&tx_ring)) 84 | { 85 | // TX done, disable transmit interrupt 86 | SCSCR0 &= ~SCSCR_TIE; 87 | } 88 | SCFSR0 &= ~SCFSR_TDFE; 89 | 90 | // read RX FIFO 91 | // Number of Data Bytes in Receive FIFO > 0 92 | while (SCFDR_RFDC > 0) 93 | { 94 | ringbuffer_write_one(&rx_ring, SCFRDR0); 95 | } 96 | SCFSR0 &= ~SCFSR_DR; 97 | SCFSR0 &= ~SCFSR_RDF; 98 | } 99 | 100 | void scif_init() 101 | { 102 | ringbuffer_init(&rx_ring, rx_buffer, RING_BUF_SIZE); 103 | ringbuffer_init(&tx_ring, tx_buffer, RING_BUF_SIZE); 104 | 105 | // disable transmit interrupt 106 | SCSCR0 &= ~SCSCR_TIE; 107 | 108 | intc_handler_function(SCIF_SCIF0_INTEVT, scif_interrupt); 109 | intc_priority(INTC_SCIF0, 1); 110 | } -------------------------------------------------------------------------------- /src/uip/memb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: memb.c,v 1.1 2006/06/12 08:21:43 adam Exp $ 34 | */ 35 | 36 | /** 37 | * \addtogroup memb 38 | * @{ 39 | */ 40 | 41 | /** 42 | * \file 43 | * Memory block allocation routines. 44 | * \author Adam Dunkels 45 | */ 46 | #include 47 | 48 | #include "memb.h" 49 | 50 | /*---------------------------------------------------------------------------*/ 51 | void 52 | memb_init(struct memb_blocks *m) 53 | { 54 | memset(m->count, 0, m->num); 55 | memset(m->mem, 0, m->size * m->num); 56 | } 57 | /*---------------------------------------------------------------------------*/ 58 | void * 59 | memb_alloc(struct memb_blocks *m) 60 | { 61 | int i; 62 | 63 | for(i = 0; i < m->num; ++i) { 64 | if(m->count[i] == 0) { 65 | /* If this block was unused, we increase the reference count to 66 | indicate that it now is used and return a pointer to the 67 | memory block. */ 68 | ++(m->count[i]); 69 | return (void *)((char *)m->mem + (i * m->size)); 70 | } 71 | } 72 | 73 | /* No free block was found, so we return NULL to indicate failure to 74 | allocate block. */ 75 | return NULL; 76 | } 77 | /*---------------------------------------------------------------------------*/ 78 | char 79 | memb_free(struct memb_blocks *m, void *ptr) 80 | { 81 | int i; 82 | char *ptr2; 83 | 84 | /* Walk through the list of blocks and try to find the block to 85 | which the pointer "ptr" points to. */ 86 | ptr2 = (char *)m->mem; 87 | for(i = 0; i < m->num; ++i) { 88 | 89 | if(ptr2 == (char *)ptr) { 90 | /* We've found to block to which "ptr" points so we decrease the 91 | reference count and return the new value of it. */ 92 | if(m->count[i] > 0) { 93 | /* Make sure that we don't deallocate free memory. */ 94 | --(m->count[i]); 95 | } 96 | return m->count[i]; 97 | } 98 | ptr2 += m->size; 99 | } 100 | return -1; 101 | } 102 | /*---------------------------------------------------------------------------*/ 103 | 104 | /** @} */ 105 | -------------------------------------------------------------------------------- /src/fxlibc/string.h: -------------------------------------------------------------------------------- 1 | #ifndef __STRING_H__ 2 | # define __STRING_H__ 3 | 4 | #include 5 | 6 | /* Copying functions. */ 7 | 8 | /* Copy __n characters from __src to __dest (overlap not allowed). */ 9 | extern void *memcpy(void *__dest, void const *__src, size_t __n); 10 | 11 | /* Copy __n characters from __src to __dest (overlap allowed). */ 12 | extern void *memmove(void *__dest, void const *__src, size_t __n); 13 | 14 | /* Copy string __src into __dest. */ 15 | extern char *strcpy(char * restrict __dest, char const * restrict __src); 16 | 17 | /* Copy at most __n characters of __src into __dest. */ 18 | extern char *strncpy(char * restrict __dest, char const * restrict __src, 19 | size_t __n); 20 | 21 | /* Concatenation functions. */ 22 | 23 | /* Copy __src at the end of __dest. */ 24 | extern char *strcat(char * restrict __dest, char const * restrict __src); 25 | 26 | /* Copy at most __n characters of __src into __dest. */ 27 | extern char *strncat(char * restrict __dest, char const * restrict __src, 28 | size_t __n); 29 | 30 | /* Comparison functions. */ 31 | 32 | /* Compare __n characters from __s1 and __s2. */ 33 | extern int memcmp(void const *__s1, void const *__s2, size_t __n); 34 | 35 | /* Compare __s1 and __s2 as strings. */ 36 | extern int strcmp(char const *__s1, char const *__s2); 37 | 38 | /* Compare __s1 and __s2 with locale-dependent collation rules. */ 39 | extern int strcoll(char const *__s1, char const *__s2); 40 | 41 | /* Compare at most __n characters of __s1 and __s2. */ 42 | extern int strncmp(char const *__s1, char const *__s2, size_t __n); 43 | 44 | /* Transform __src into __dest in a way that morphs strcoll into strcmp. */ 45 | extern size_t strxfrm(char * restrict __dest, char const * restrict __src, 46 | size_t __n); 47 | 48 | /* Search functions. */ 49 | 50 | /* Search __c within the first __n characters of __s. */ 51 | extern void *memchr(void const *__s, int __c, size_t __n); 52 | 53 | /* Find the first occurrence of __c within __s. */ 54 | extern char *strchr(char const *__s, int __c); 55 | 56 | /* Count initial characters of __s that are not in __exclude. */ 57 | extern size_t strcspn(char const *__s, char const *__exclude); 58 | 59 | /* Find the first character of __s that is also in __include. */ 60 | extern char *strpbrk(char const *__s, char const *__include); 61 | 62 | /* Find the last occurrence of __c within __s. */ 63 | extern char *strrchr(char const *__s, int __c); 64 | 65 | /* Count initial characters of __s that are in __include. */ 66 | extern size_t strspn(char const *__s, char const *__include); 67 | 68 | /* Find the first occurrence of __s2 as a substring of __s1. */ 69 | extern char *strstr(char const *__s1, char const *__s2); 70 | 71 | /* Break __s into tokens delimited by characters from __separators. */ 72 | extern char *strtok(char * restrict __s, char const * restrict __separators); 73 | 74 | /* Miscellaneous functions. */ 75 | 76 | /* Fill the __n first bytes of __s with character __c. */ 77 | extern void *memset(void *__s, int __c, size_t __n); 78 | 79 | /* Returns a string that describes the errno value __errnum. */ 80 | extern char *strerror(int __errnum); 81 | 82 | /* Length of __s. */ 83 | extern size_t strlen(char const *__s); 84 | 85 | /* 86 | ** Extensions 87 | */ 88 | 89 | /* The following functions are not specified by C99, but convenient. */ 90 | 91 | /* Minimum of __n and the length of __s. */ 92 | extern size_t strnlen(char const *__s, size_t __n); 93 | 94 | /* Like strchr, but returns the end of __s if __c is not found. */ 95 | extern char *strchrnul(char const *__s, int __c); 96 | 97 | /* Compare __s1 and __s2 case-insensitively. */ 98 | extern int strcasecmp(char const *__s1, char const *__s2); 99 | 100 | /* Compare at most __n characters of __s1 and __s2 case-insensitively. */ 101 | extern int strncasecmp(char const *__s1, char const *__s2, size_t __n); 102 | 103 | /* Find __needle in __haystack, ignoring case. */ 104 | extern char *strcasestr(char const *__haystack, char const *__needle); 105 | 106 | /* Duplicate __s with malloc. */ 107 | extern char *strdup(char const *__s); 108 | 109 | /* Duplicate at most __n characters of __s with malloc. */ 110 | extern char *strndup(char const *__s, size_t __n); 111 | 112 | #endif /*__STRING_H__*/ 113 | -------------------------------------------------------------------------------- /src/uip/lc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004-2005, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: lc.h,v 1.2 2006/06/12 08:00:30 adam Exp $ 34 | */ 35 | 36 | /** 37 | * \addtogroup pt 38 | * @{ 39 | */ 40 | 41 | /** 42 | * \defgroup lc Local continuations 43 | * @{ 44 | * 45 | * Local continuations form the basis for implementing protothreads. A 46 | * local continuation can be set in a specific function to 47 | * capture the state of the function. After a local continuation has 48 | * been set can be resumed in order to restore the state of the 49 | * function at the point where the local continuation was set. 50 | * 51 | * 52 | */ 53 | 54 | /** 55 | * \file lc.h 56 | * Local continuations 57 | * \author 58 | * Adam Dunkels 59 | * 60 | */ 61 | 62 | #ifdef DOXYGEN 63 | /** 64 | * Initialize a local continuation. 65 | * 66 | * This operation initializes the local continuation, thereby 67 | * unsetting any previously set continuation state. 68 | * 69 | * \hideinitializer 70 | */ 71 | #define LC_INIT(lc) 72 | 73 | /** 74 | * Set a local continuation. 75 | * 76 | * The set operation saves the state of the function at the point 77 | * where the operation is executed. As far as the set operation is 78 | * concerned, the state of the function does not include the 79 | * call-stack or local (automatic) variables, but only the program 80 | * counter and such CPU registers that needs to be saved. 81 | * 82 | * \hideinitializer 83 | */ 84 | #define LC_SET(lc) 85 | 86 | /** 87 | * Resume a local continuation. 88 | * 89 | * The resume operation resumes a previously set local continuation, thus 90 | * restoring the state in which the function was when the local 91 | * continuation was set. If the local continuation has not been 92 | * previously set, the resume operation does nothing. 93 | * 94 | * \hideinitializer 95 | */ 96 | #define LC_RESUME(lc) 97 | 98 | /** 99 | * Mark the end of local continuation usage. 100 | * 101 | * The end operation signifies that local continuations should not be 102 | * used any more in the function. This operation is not needed for 103 | * most implementations of local continuation, but is required by a 104 | * few implementations. 105 | * 106 | * \hideinitializer 107 | */ 108 | #define LC_END(lc) 109 | 110 | /** 111 | * \var typedef lc_t; 112 | * 113 | * The local continuation type. 114 | * 115 | * \hideinitializer 116 | */ 117 | #endif /* DOXYGEN */ 118 | 119 | #ifndef __LC_H__ 120 | #define __LC_H__ 121 | 122 | #ifdef LC_CONF_INCLUDE 123 | #include LC_CONF_INCLUDE 124 | #else 125 | #include "lc-switch.h" 126 | #endif /* LC_CONF_INCLUDE */ 127 | 128 | #endif /* __LC_H__ */ 129 | 130 | /** @} */ 131 | /** @} */ 132 | -------------------------------------------------------------------------------- /src/uip-conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup uipopt 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \name Project-specific configuration options 8 | * @{ 9 | * 10 | * uIP has a number of configuration options that can be overridden 11 | * for each project. These are kept in a project-specific uip-conf.h 12 | * file and all configuration names have the prefix UIP_CONF. 13 | */ 14 | 15 | /* 16 | * Copyright (c) 2006, Swedish Institute of Computer Science. 17 | * All rights reserved. 18 | * 19 | * Redistribution and use in source and binary forms, with or without 20 | * modification, are permitted provided that the following conditions 21 | * are met: 22 | * 1. Redistributions of source code must retain the above copyright 23 | * notice, this list of conditions and the following disclaimer. 24 | * 2. Redistributions in binary form must reproduce the above copyright 25 | * notice, this list of conditions and the following disclaimer in the 26 | * documentation and/or other materials provided with the distribution. 27 | * 3. Neither the name of the Institute nor the names of its contributors 28 | * may be used to endorse or promote products derived from this software 29 | * without specific prior written permission. 30 | * 31 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 32 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 35 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41 | * SUCH DAMAGE. 42 | * 43 | * This file is part of the uIP TCP/IP stack 44 | * 45 | * $Id: uip-conf.h,v 1.6 2006/06/12 08:00:31 adam Exp $ 46 | */ 47 | 48 | /** 49 | * \file 50 | * An example uIP configuration file 51 | * \author 52 | * Adam Dunkels 53 | */ 54 | 55 | #ifndef __UIP_CONF_H__ 56 | #define __UIP_CONF_H__ 57 | 58 | //#include 59 | #include 60 | 61 | /** 62 | * 8 bit datatype 63 | * 64 | * This typedef defines the 8-bit type used throughout uIP. 65 | * 66 | * \hideinitializer 67 | */ 68 | typedef uint8_t u8_t; 69 | 70 | /** 71 | * 16 bit datatype 72 | * 73 | * This typedef defines the 16-bit type used throughout uIP. 74 | * 75 | * \hideinitializer 76 | */ 77 | typedef uint16_t u16_t; 78 | 79 | /** 80 | * Statistics datatype 81 | * 82 | * This typedef defines the dataype used for keeping statistics in 83 | * uIP. 84 | * 85 | * \hideinitializer 86 | */ 87 | typedef unsigned short uip_stats_t; 88 | 89 | /** 90 | * Maximum number of TCP connections. 91 | * 92 | * \hideinitializer 93 | */ 94 | #define UIP_CONF_MAX_CONNECTIONS 10 95 | 96 | /** 97 | * Maximum number of listening TCP ports. 98 | * 99 | * \hideinitializer 100 | */ 101 | #define UIP_CONF_MAX_LISTENPORTS 10 102 | 103 | /** 104 | * uIP buffer size. 105 | * 106 | * \hideinitializer 107 | */ 108 | #define UIP_CONF_BUFFER_SIZE 1500 109 | 110 | /** 111 | * CPU byte order. 112 | * 113 | * \hideinitializer 114 | */ 115 | #define UIP_CONF_BYTE_ORDER UIP_BIG_ENDIAN 116 | 117 | /** 118 | * Logging on or off 119 | * 120 | * \hideinitializer 121 | */ 122 | #define UIP_CONF_LOGGING 1 123 | 124 | /** 125 | * UDP support on or off 126 | * 127 | * \hideinitializer 128 | */ 129 | #define UIP_CONF_UDP 0 130 | 131 | /** 132 | * UDP checksums on or off 133 | * 134 | * \hideinitializer 135 | */ 136 | #define UIP_CONF_UDP_CHECKSUMS 0 137 | 138 | /** 139 | * uIP statistics on or off 140 | * 141 | * \hideinitializer 142 | */ 143 | #define UIP_CONF_STATISTICS 1 144 | 145 | #define UIP_CONF_LLH_LEN 0 146 | 147 | /* Here we include the header file for the application(s) we use in 148 | our project. */ 149 | /*#include "smtp.h"*/ 150 | /*#include "uip/hello-world.h"*/ 151 | //#include "uip/httpd.h" 152 | /*#include "uip/webserver.h"*/ 153 | #include "uip/irc.h" 154 | /*#include "dhcpc.h"*/ 155 | /*#include "resolv.h"*/ 156 | /*#include "webclient.h"*/ 157 | 158 | #endif /* __UIP_CONF_H__ */ 159 | 160 | /** @} */ 161 | /** @} */ 162 | -------------------------------------------------------------------------------- /src/uip/timer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup timer 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \file 8 | * Timer library implementation. 9 | * \author 10 | * Adam Dunkels 11 | */ 12 | 13 | /* 14 | * Copyright (c) 2004, Swedish Institute of Computer Science. 15 | * All rights reserved. 16 | * 17 | * Redistribution and use in source and binary forms, with or without 18 | * modification, are permitted provided that the following conditions 19 | * are met: 20 | * 1. Redistributions of source code must retain the above copyright 21 | * notice, this list of conditions and the following disclaimer. 22 | * 2. Redistributions in binary form must reproduce the above copyright 23 | * notice, this list of conditions and the following disclaimer in the 24 | * documentation and/or other materials provided with the distribution. 25 | * 3. Neither the name of the Institute nor the names of its contributors 26 | * may be used to endorse or promote products derived from this software 27 | * without specific prior written permission. 28 | * 29 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 30 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 33 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | * SUCH DAMAGE. 40 | * 41 | * This file is part of the uIP TCP/IP stack 42 | * 43 | * Author: Adam Dunkels 44 | * 45 | * $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $ 46 | */ 47 | 48 | #include "clock.h" 49 | #include "timer.h" 50 | 51 | /*---------------------------------------------------------------------------*/ 52 | /** 53 | * Set a timer. 54 | * 55 | * This function is used to set a timer for a time sometime in the 56 | * future. The function timer_expired() will evaluate to true after 57 | * the timer has expired. 58 | * 59 | * \param t A pointer to the timer 60 | * \param interval The interval before the timer expires. 61 | * 62 | */ 63 | void 64 | timer_set(struct timer *t, clock_time_t interval) 65 | { 66 | t->interval = interval; 67 | t->start = clock_time(); 68 | } 69 | /*---------------------------------------------------------------------------*/ 70 | /** 71 | * Reset the timer with the same interval. 72 | * 73 | * This function resets the timer with the same interval that was 74 | * given to the timer_set() function. The start point of the interval 75 | * is the exact time that the timer last expired. Therefore, this 76 | * function will cause the timer to be stable over time, unlike the 77 | * timer_rester() function. 78 | * 79 | * \param t A pointer to the timer. 80 | * 81 | * \sa timer_restart() 82 | */ 83 | void 84 | timer_reset(struct timer *t) 85 | { 86 | t->start += t->interval; 87 | } 88 | /*---------------------------------------------------------------------------*/ 89 | /** 90 | * Restart the timer from the current point in time 91 | * 92 | * This function restarts a timer with the same interval that was 93 | * given to the timer_set() function. The timer will start at the 94 | * current time. 95 | * 96 | * \note A periodic timer will drift if this function is used to reset 97 | * it. For preioric timers, use the timer_reset() function instead. 98 | * 99 | * \param t A pointer to the timer. 100 | * 101 | * \sa timer_reset() 102 | */ 103 | void 104 | timer_restart(struct timer *t) 105 | { 106 | t->start = clock_time(); 107 | } 108 | /*---------------------------------------------------------------------------*/ 109 | /** 110 | * Check if a timer has expired. 111 | * 112 | * This function tests if a timer has expired and returns true or 113 | * false depending on its status. 114 | * 115 | * \param t A pointer to the timer 116 | * 117 | * \return Non-zero if the timer has expired, zero otherwise. 118 | * 119 | */ 120 | int 121 | timer_expired(struct timer *t) 122 | { 123 | return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval; 124 | } 125 | /*---------------------------------------------------------------------------*/ 126 | 127 | /** @} */ 128 | -------------------------------------------------------------------------------- /src/uip/uip_arch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup uip 3 | * {@ 4 | */ 5 | 6 | /** 7 | * \defgroup uiparch Architecture specific uIP functions 8 | * @{ 9 | * 10 | * The functions in the architecture specific module implement the IP 11 | * check sum and 32-bit additions. 12 | * 13 | * The IP checksum calculation is the most computationally expensive 14 | * operation in the TCP/IP stack and it therefore pays off to 15 | * implement this in efficient assembler. The purpose of the uip-arch 16 | * module is to let the checksum functions to be implemented in 17 | * architecture specific assembler. 18 | * 19 | */ 20 | 21 | /** 22 | * \file 23 | * Declarations of architecture specific functions. 24 | * \author Adam Dunkels 25 | */ 26 | 27 | /* 28 | * Copyright (c) 2001, Adam Dunkels. 29 | * All rights reserved. 30 | * 31 | * Redistribution and use in source and binary forms, with or without 32 | * modification, are permitted provided that the following conditions 33 | * are met: 34 | * 1. Redistributions of source code must retain the above copyright 35 | * notice, this list of conditions and the following disclaimer. 36 | * 2. Redistributions in binary form must reproduce the above copyright 37 | * notice, this list of conditions and the following disclaimer in the 38 | * documentation and/or other materials provided with the distribution. 39 | * 3. The name of the author may not be used to endorse or promote 40 | * products derived from this software without specific prior 41 | * written permission. 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 44 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 45 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 47 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 49 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 51 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 52 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 53 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 | * 55 | * This file is part of the uIP TCP/IP stack. 56 | * 57 | * $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $ 58 | * 59 | */ 60 | 61 | #ifndef __UIP_ARCH_H__ 62 | #define __UIP_ARCH_H__ 63 | 64 | #include "uip.h" 65 | 66 | /** 67 | * Carry out a 32-bit addition. 68 | * 69 | * Because not all architectures for which uIP is intended has native 70 | * 32-bit arithmetic, uIP uses an external C function for doing the 71 | * required 32-bit additions in the TCP protocol processing. This 72 | * function should add the two arguments and place the result in the 73 | * global variable uip_acc32. 74 | * 75 | * \note The 32-bit integer pointed to by the op32 parameter and the 76 | * result in the uip_acc32 variable are in network byte order (big 77 | * endian). 78 | * 79 | * \param op32 A pointer to a 4-byte array representing a 32-bit 80 | * integer in network byte order (big endian). 81 | * 82 | * \param op16 A 16-bit integer in host byte order. 83 | */ 84 | void uip_add32(u8_t *op32, u16_t op16); 85 | 86 | /** 87 | * Calculate the Internet checksum over a buffer. 88 | * 89 | * The Internet checksum is the one's complement of the one's 90 | * complement sum of all 16-bit words in the buffer. 91 | * 92 | * See RFC1071. 93 | * 94 | * \note This function is not called in the current version of uIP, 95 | * but future versions might make use of it. 96 | * 97 | * \param buf A pointer to the buffer over which the checksum is to be 98 | * computed. 99 | * 100 | * \param len The length of the buffer over which the checksum is to 101 | * be computed. 102 | * 103 | * \return The Internet checksum of the buffer. 104 | */ 105 | u16_t uip_chksum(u16_t *buf, u16_t len); 106 | 107 | /** 108 | * Calculate the IP header checksum of the packet header in uip_buf. 109 | * 110 | * The IP header checksum is the Internet checksum of the 20 bytes of 111 | * the IP header. 112 | * 113 | * \return The IP header checksum of the IP header in the uip_buf 114 | * buffer. 115 | */ 116 | u16_t uip_ipchksum(void); 117 | 118 | /** 119 | * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. 120 | * 121 | * The TCP checksum is the Internet checksum of data contents of the 122 | * TCP segment, and a pseudo-header as defined in RFC793. 123 | * 124 | * \note The uip_appdata pointer that points to the packet data may 125 | * point anywhere in memory, so it is not possible to simply calculate 126 | * the Internet checksum of the contents of the uip_buf buffer. 127 | * 128 | * \return The TCP checksum of the TCP segment in uip_buf and pointed 129 | * to by uip_appdata. 130 | */ 131 | u16_t uip_tcpchksum(void); 132 | 133 | u16_t uip_udpchksum(void); 134 | 135 | /** @} */ 136 | /** @} */ 137 | 138 | #endif /* __UIP_ARCH_H__ */ 139 | -------------------------------------------------------------------------------- /src/uip/memb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: memb.h,v 1.1 2006/06/12 08:21:43 adam Exp $ 34 | */ 35 | 36 | /** 37 | * \defgroup memb Memory block management functions 38 | * 39 | * The memory block allocation routines provide a simple yet powerful 40 | * set of functions for managing a set of memory blocks of fixed 41 | * size. A set of memory blocks is statically declared with the 42 | * MEMB() macro. Memory blocks are allocated from the declared 43 | * memory by the memb_alloc() function, and are deallocated with the 44 | * memb_free() function. 45 | * 46 | * \note Because of namespace clashes only one MEMB() can be 47 | * declared per C module, and the name scope of a MEMB() memory 48 | * block is local to each C module. 49 | * 50 | * The following example shows how to declare and use a memory block 51 | * called "cmem" which has 8 chunks of memory with each memory chunk 52 | * being 20 bytes large. 53 | * 54 | * @{ 55 | */ 56 | 57 | 58 | /** 59 | * \file 60 | * Memory block allocation routines. 61 | * \author 62 | * Adam Dunkels 63 | * 64 | */ 65 | 66 | #ifndef __MEMB_H__ 67 | #define __MEMB_H__ 68 | 69 | /* 70 | * Here we define a C preprocessing macro for concatenating to 71 | * strings. We need use two macros in order to allow concatenation of 72 | * two #defined macros. 73 | */ 74 | #define MEMB_CONCAT2(s1, s2) s1##s2 75 | #define MEMB_CONCAT(s1, s2) MEMB_CONCAT2(s1, s2) 76 | 77 | /** 78 | * Declare a memory block. 79 | * 80 | * This macro is used to staticall declare a block of memory that can 81 | * be used by the block allocation functions. The macro statically 82 | * declares a C array with a size that matches the specified number of 83 | * blocks and their individual sizes. 84 | * 85 | * Example: 86 | \code 87 | MEMB(connections, sizeof(struct connection), 16); 88 | \endcode 89 | * 90 | * \param name The name of the memory block (later used with 91 | * memb_init(), memb_alloc() and memb_free()). 92 | * 93 | * \param size The size of each memory chunk, in bytes. 94 | * 95 | * \param num The total number of memory chunks in the block. 96 | * 97 | */ 98 | #define MEMB(name, structure, num) \ 99 | static char MEMB_CONCAT(name,_memb_count)[num]; \ 100 | static structure MEMB_CONCAT(name,_memb_mem)[num]; \ 101 | static struct memb_blocks name = {sizeof(structure), num, \ 102 | MEMB_CONCAT(name,_memb_count), \ 103 | (void *)MEMB_CONCAT(name,_memb_mem)} 104 | 105 | struct memb_blocks { 106 | unsigned short size; 107 | unsigned short num; 108 | char *count; 109 | void *mem; 110 | }; 111 | 112 | /** 113 | * Initialize a memory block that was declared with MEMB(). 114 | * 115 | * \param m A memory block previosly declared with MEMB(). 116 | */ 117 | void memb_init(struct memb_blocks *m); 118 | 119 | /** 120 | * Allocate a memory block from a block of memory declared with MEMB(). 121 | * 122 | * \param m A memory block previosly declared with MEMB(). 123 | */ 124 | void *memb_alloc(struct memb_blocks *m); 125 | 126 | /** 127 | * Deallocate a memory block from a memory block previously declared 128 | * with MEMB(). 129 | * 130 | * \param m m A memory block previosly declared with MEMB(). 131 | * 132 | * \param ptr A pointer to the memory block that is to be deallocated. 133 | * 134 | * \return The new reference count for the memory block (should be 0 135 | * if successfully deallocated) or -1 if the pointer "ptr" did not 136 | * point to a legal memory block. 137 | */ 138 | char memb_free(struct memb_blocks *m, void *ptr); 139 | 140 | /** @} */ 141 | 142 | #endif /* __MEMB_H__ */ 143 | -------------------------------------------------------------------------------- /src/uip/uip_arp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup uip 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \addtogroup uiparp 8 | * @{ 9 | */ 10 | 11 | /** 12 | * \file 13 | * Macros and definitions for the ARP module. 14 | * \author Adam Dunkels 15 | */ 16 | 17 | 18 | /* 19 | * Copyright (c) 2001-2003, Adam Dunkels. 20 | * All rights reserved. 21 | * 22 | * Redistribution and use in source and binary forms, with or without 23 | * modification, are permitted provided that the following conditions 24 | * are met: 25 | * 1. Redistributions of source code must retain the above copyright 26 | * notice, this list of conditions and the following disclaimer. 27 | * 2. Redistributions in binary form must reproduce the above copyright 28 | * notice, this list of conditions and the following disclaimer in the 29 | * documentation and/or other materials provided with the distribution. 30 | * 3. The name of the author may not be used to endorse or promote 31 | * products derived from this software without specific prior 32 | * written permission. 33 | * 34 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 35 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 36 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 38 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 42 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 43 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 44 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 | * 46 | * This file is part of the uIP TCP/IP stack. 47 | * 48 | * $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $ 49 | * 50 | */ 51 | 52 | #ifndef __UIP_ARP_H__ 53 | #define __UIP_ARP_H__ 54 | 55 | #include "uip.h" 56 | 57 | 58 | extern struct uip_eth_addr uip_ethaddr; 59 | 60 | /** 61 | * The Ethernet header. 62 | */ 63 | struct uip_eth_hdr { 64 | struct uip_eth_addr dest; 65 | struct uip_eth_addr src; 66 | u16_t type; 67 | }; 68 | 69 | #define UIP_ETHTYPE_ARP 0x0806 70 | #define UIP_ETHTYPE_IP 0x0800 71 | #define UIP_ETHTYPE_IP6 0x86dd 72 | 73 | 74 | /* The uip_arp_init() function must be called before any of the other 75 | ARP functions. */ 76 | void uip_arp_init(void); 77 | 78 | /* The uip_arp_ipin() function should be called whenever an IP packet 79 | arrives from the Ethernet. This function refreshes the ARP table or 80 | inserts a new mapping if none exists. The function assumes that an 81 | IP packet with an Ethernet header is present in the uip_buf buffer 82 | and that the length of the packet is in the uip_len variable. */ 83 | /*void uip_arp_ipin(void);*/ 84 | #define uip_arp_ipin() 85 | 86 | /* The uip_arp_arpin() should be called when an ARP packet is received 87 | by the Ethernet driver. This function also assumes that the 88 | Ethernet frame is present in the uip_buf buffer. When the 89 | uip_arp_arpin() function returns, the contents of the uip_buf 90 | buffer should be sent out on the Ethernet if the uip_len variable 91 | is > 0. */ 92 | void uip_arp_arpin(void); 93 | 94 | /* The uip_arp_out() function should be called when an IP packet 95 | should be sent out on the Ethernet. This function creates an 96 | Ethernet header before the IP header in the uip_buf buffer. The 97 | Ethernet header will have the correct Ethernet MAC destination 98 | address filled in if an ARP table entry for the destination IP 99 | address (or the IP address of the default router) is present. If no 100 | such table entry is found, the IP packet is overwritten with an ARP 101 | request and we rely on TCP to retransmit the packet that was 102 | overwritten. In any case, the uip_len variable holds the length of 103 | the Ethernet frame that should be transmitted. */ 104 | void uip_arp_out(void); 105 | 106 | /* The uip_arp_timer() function should be called every ten seconds. It 107 | is responsible for flushing old entries in the ARP table. */ 108 | void uip_arp_timer(void); 109 | 110 | /** @} */ 111 | 112 | /** 113 | * \addtogroup uipconffunc 114 | * @{ 115 | */ 116 | 117 | 118 | /** 119 | * Specifiy the Ethernet MAC address. 120 | * 121 | * The ARP code needs to know the MAC address of the Ethernet card in 122 | * order to be able to respond to ARP queries and to generate working 123 | * Ethernet headers. 124 | * 125 | * \note This macro only specifies the Ethernet MAC address to the ARP 126 | * code. It cannot be used to change the MAC address of the Ethernet 127 | * card. 128 | * 129 | * \param eaddr A pointer to a struct uip_eth_addr containing the 130 | * Ethernet MAC address of the Ethernet card. 131 | * 132 | * \hideinitializer 133 | */ 134 | #define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ 135 | uip_ethaddr.addr[1] = eaddr.addr[1];\ 136 | uip_ethaddr.addr[2] = eaddr.addr[2];\ 137 | uip_ethaddr.addr[3] = eaddr.addr[3];\ 138 | uip_ethaddr.addr[4] = eaddr.addr[4];\ 139 | uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) 140 | 141 | /** @} */ 142 | /** @} */ 143 | 144 | #endif /* __UIP_ARP_H__ */ 145 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | # Default Makefile for fxSDK add-ins. This file was probably copied there by 3 | # the [fxsdk] program. 4 | #--- 5 | 6 | # 7 | # Configuration 8 | # 9 | 10 | include project.cfg 11 | 12 | # Compiler flags 13 | CFLAGSFX = $(CFLAGS) $(CFLAGS_FX) $(INCLUDE_FX) -Wl,--print-memory-usage 14 | CFLAGSCG = $(CFLAGS) $(CFLAGS_CG) $(INCLUDE_CG) -Wl,--print-memory-usage 15 | 16 | # Linker flags 17 | LDFLAGSFX := $(LDFLAGS) $(LDFLAGS_FX) 18 | LDFLAGSCG := $(LDFLAGS) $(LDFLAGS_CG) 19 | 20 | # Dependency list generation flags 21 | depflags = -MMD -MT $@ -MF $(@:.o=.d) -MP 22 | # ELF to binary flags 23 | BINFLAGS := -R .bss -R .gint_bss 24 | 25 | # G1A and G3A generation flags 26 | NAME_G1A ?= $(NAME) 27 | NAME_G3A ?= $(NAME) 28 | G1AF := -i "$(ICON_FX)" -n "$(NAME_G1A)" --internal="$(INTERNAL)" 29 | G3AF := -n basic:"$(NAME_G3A)" -i uns:"$(ICON_CG_UNS)" -i sel:"$(ICON_CG_SEL)" 30 | 31 | ifeq "$(TOOLCHAIN_FX)" "" 32 | TOOLCHAIN_FX := sh3eb-elf 33 | endif 34 | 35 | ifeq "$(TOOLCHAIN_CG)" "" 36 | TOOLCHAIN_CG := sh4eb-elf 37 | endif 38 | 39 | # fxconv flags 40 | FXCONVFX := --fx --toolchain=$(TOOLCHAIN_FX) 41 | FXCONVCG := --cg --toolchain=$(TOOLCHAIN_CG) 42 | 43 | # Determine the compiler install and include path 44 | GCC_BASE_FX := $(shell $(TOOLCHAIN_FX)-gcc --print-search-dirs | grep install | sed 's/install: //') 45 | GCC_BASE_CG := $(shell $(TOOLCHAIN_CG)-gcc --print-search-dirs | grep install | sed 's/install: //') 46 | GCC_INCLUDE_FX := $(GCC_BASE_FX)/include 47 | GCC_INCLUDE_CG := $(GCC_BASE_CG)/include 48 | 49 | INCLUDE_FX += -I $(GCC_INCLUDE_FX)/gint/std/ 50 | INCLUDE_CG += -I $(GCC_INCLUDE_FX)/gint/std/ 51 | 52 | # 53 | # File listings 54 | # 55 | 56 | NULL := 57 | TARGET := $(subst $(NULL) $(NULL),-,$(NAME)) 58 | 59 | ifeq "$(TARGET_FX)" "" 60 | TARGET_FX := $(TARGET).g1a 61 | endif 62 | 63 | ifeq "$(TARGET_CG)" "" 64 | TARGET_CG := $(TARGET).g3a 65 | endif 66 | 67 | ELF_FX := build-fx/$(shell basename "$(TARGET_FX)" .g1a).elf 68 | BIN_FX := $(ELF_FX:.elf=.bin) 69 | 70 | ELF_CG := build-cg/$(shell basename "$(TARGET_CG)" .g3a).elf 71 | BIN_CG := $(ELF_CG:.elf=.bin) 72 | 73 | # Source files 74 | src := $(shell find src/ -name '*.[csS]') 75 | assets-fx := $(shell find assets-fx/*/ -type f -not -name 'fxconv-metadata.txt') 76 | assets-cg := $(shell find assets-cg/*/ -type f -not -name 'fxconv-metadata.txt') 77 | meta-fx := $(shell find assets-fx -name 'fxconv-metadata.txt') 78 | meta-cg := $(shell find assets-cg -name 'fxconv-metadata.txt') 79 | 80 | # Object files 81 | obj-fx := $(src:%=build-fx/%.o) $(assets-fx:assets-fx/%=build-fx/assets/%.o) 82 | obj-cg := $(src:%=build-cg/%.o) $(assets-cg:assets-cg/%=build-cg/assets/%.o) 83 | 84 | # Additional dependencies 85 | deps-fx := $(ICON_FX) 86 | deps-cg := $(ICON_CG_UNS) $(ICON_CG_SEL) 87 | 88 | # All targets 89 | all := 90 | ifneq "$(wildcard build-fx)" "" 91 | all += all-fx 92 | endif 93 | ifneq "$(wildcard build-cg)" "" 94 | all += all-cg 95 | endif 96 | 97 | # 98 | # Build rules 99 | # 100 | 101 | all: $(all) 102 | 103 | all-fx: $(TARGET_FX) 104 | all-cg: $(TARGET_CG) 105 | 106 | $(TARGET_FX): $(obj-fx) $(deps-fx) 107 | @ mkdir -p $(dir $@) 108 | $(TOOLCHAIN_FX)-gcc -o $(ELF_FX) $(obj-fx) $(CFLAGSFX) $(LDFLAGSFX) 109 | $(TOOLCHAIN_FX)-objcopy -O binary $(BINFLAGS) $(ELF_FX) $(BIN_FX) 110 | fxg1a $(BIN_FX) -o $@ $(G1AF) 111 | 112 | $(TARGET_CG): $(obj-cg) $(deps-cg) 113 | @ mkdir -p $(dir $@) 114 | $(TOOLCHAIN_CG)-gcc -o $(ELF_CG) $(obj-cg) $(CFLAGSCG) $(LDFLAGSCG) 115 | $(TOOLCHAIN_CG)-objcopy -O binary $(BINFLAGS) $(ELF_CG) $(BIN_CG) 116 | mkg3a $(G3AF) $(BIN_CG) $@ 117 | 118 | # C sources 119 | build-fx/%.c.o: %.c 120 | @ mkdir -p $(dir $@) 121 | $(TOOLCHAIN_FX)-gcc -c $< -o $@ $(CFLAGSFX) $(depflags) 122 | build-cg/%.c.o: %.c 123 | @ mkdir -p $(dir $@) 124 | $(TOOLCHAIN_CG)-gcc -c $< -o $@ $(CFLAGSCG) $(depflags) 125 | 126 | # Assembler sources 127 | build-fx/%.s.o: %.s 128 | @ mkdir -p $(dir $@) 129 | $(TOOLCHAIN_FX)-gcc -c $< -o $@ -Wa,--dsp 130 | build-cg/%.s.o: %.s 131 | @ mkdir -p $(dir $@) 132 | $(TOOLCHAIN_CG)-gcc -c $< -o $@ -Wa,--dsp 133 | 134 | # Preprocessed assembler sources 135 | build-fx/%.S.o: %.S 136 | @ mkdir -p $(dir $@) 137 | $(TOOLCHAIN_FX)-gcc -c $< -o $@ $(INCLUDE_FX) -Wa,--dsp 138 | build-cg/%.S.o: %.S 139 | @ mkdir -p $(dir $@) 140 | $(TOOLCHAIN_CG)-gcc -c $< -o $@ $(INCLUDE_CG) -Wa,--dsp 141 | 142 | # Assets 143 | build-fx/assets/%.o: assets-fx/% $(meta-fx) 144 | @ mkdir -p $(dir $@) 145 | fxconv $< -o $@ $(FXCONVFX) 146 | build-cg/assets/%.o: assets-cg/% $(meta-cg) 147 | @ mkdir -p $(dir $@) 148 | fxconv $< -o $@ $(FXCONVCG) 149 | 150 | # 151 | # Cleaning and utilities 152 | # 153 | 154 | # Dependency information 155 | -include $(shell find build* -name *.d 2> /dev/null) 156 | build-fx/%.d: ; 157 | build-cg/%.d: ; 158 | .PRECIOUS: build-fx build-cg build-fx/%.d build-cg/%.d %/ 159 | 160 | clean-fx: 161 | @ rm -rf build-fx/ 162 | clean-cg: 163 | @ rm -rf build-cg/ 164 | 165 | distclean-fx: clean-fx 166 | @ rm -f $(TARGET_FX) 167 | distclean-cg: clean-cg 168 | @ rm -f $(TARGET_CG) 169 | 170 | clean: clean-fx clean-cg 171 | 172 | distclean: distclean-fx distclean-cg 173 | 174 | install-fx: $(TARGET_FX) 175 | p7 send -f $< 176 | install-cg: $(TARGET_CG) 177 | @ while [[ ! -h /dev/Prizm1 ]]; do sleep 0.25; done 178 | @ while ! mount /dev/Prizm1; do sleep 0.25; done 179 | @ rm -f /mnt/prizm/$< 180 | @ cp $< /mnt/prizm 181 | @ umount /dev/Prizm1 182 | @- eject /dev/Prizm1 183 | 184 | .PHONY: all all-fx all-cg clean distclean install-fx install-cg 185 | -------------------------------------------------------------------------------- /src/uip/uip-neighbor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * $Id: uip-neighbor.c,v 1.2 2006/06/12 08:00:30 adam Exp $ 32 | */ 33 | 34 | /** 35 | * \file 36 | * Database of link-local neighbors, used by IPv6 code and 37 | * to be used by a future ARP code rewrite. 38 | * \author 39 | * Adam Dunkels 40 | */ 41 | 42 | #include "uip-neighbor.h" 43 | 44 | #include 45 | #include "log.h" 46 | #define MAX_TIME 128 47 | 48 | #ifdef UIP_NEIGHBOR_CONF_ENTRIES 49 | #define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES 50 | #else /* UIP_NEIGHBOR_CONF_ENTRIES */ 51 | #define ENTRIES 8 52 | #endif /* UIP_NEIGHBOR_CONF_ENTRIES */ 53 | 54 | struct neighbor_entry { 55 | uip_ipaddr_t ipaddr; 56 | struct uip_neighbor_addr addr; 57 | u8_t time; 58 | }; 59 | static struct neighbor_entry entries[ENTRIES]; 60 | 61 | /*---------------------------------------------------------------------------*/ 62 | void 63 | uip_neighbor_init(void) 64 | { 65 | int i; 66 | 67 | for(i = 0; i < ENTRIES; ++i) { 68 | entries[i].time = MAX_TIME; 69 | } 70 | } 71 | /*---------------------------------------------------------------------------*/ 72 | void 73 | uip_neighbor_periodic(void) 74 | { 75 | int i; 76 | 77 | for(i = 0; i < ENTRIES; ++i) { 78 | if(entries[i].time < MAX_TIME) { 79 | entries[i].time++; 80 | } 81 | } 82 | } 83 | /*---------------------------------------------------------------------------*/ 84 | void 85 | uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr) 86 | { 87 | int i, oldest; 88 | u8_t oldest_time; 89 | 90 | /*myprintf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", 91 | addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3], 92 | addr->addr.addr[4], addr->addr.addr[5]);*/ 93 | 94 | /* Find the first unused entry or the oldest used entry. */ 95 | oldest_time = 0; 96 | oldest = 0; 97 | for(i = 0; i < ENTRIES; ++i) { 98 | if(entries[i].time == MAX_TIME) { 99 | oldest = i; 100 | break; 101 | } 102 | if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) { 103 | oldest = i; 104 | break; 105 | } 106 | if(entries[i].time > oldest_time) { 107 | oldest = i; 108 | oldest_time = entries[i].time; 109 | } 110 | } 111 | 112 | /* Use the oldest or first free entry (either pointed to by the 113 | "oldest" variable). */ 114 | entries[oldest].time = 0; 115 | uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr); 116 | memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr)); 117 | } 118 | /*---------------------------------------------------------------------------*/ 119 | static struct neighbor_entry * 120 | find_entry(uip_ipaddr_t ipaddr) 121 | { 122 | int i; 123 | 124 | for(i = 0; i < ENTRIES; ++i) { 125 | if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) { 126 | return &entries[i]; 127 | } 128 | } 129 | return NULL; 130 | } 131 | /*---------------------------------------------------------------------------*/ 132 | void 133 | uip_neighbor_update(uip_ipaddr_t ipaddr) 134 | { 135 | struct neighbor_entry *e; 136 | 137 | e = find_entry(ipaddr); 138 | if(e != NULL) { 139 | e->time = 0; 140 | } 141 | } 142 | /*---------------------------------------------------------------------------*/ 143 | struct uip_neighbor_addr * 144 | uip_neighbor_lookup(uip_ipaddr_t ipaddr) 145 | { 146 | struct neighbor_entry *e; 147 | 148 | e = find_entry(ipaddr); 149 | if(e != NULL) { 150 | /* myprintf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", 151 | e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3], 152 | e->addr.addr.addr[4], e->addr.addr.addr[5]);*/ 153 | 154 | return &e->addr; 155 | } 156 | return NULL; 157 | } 158 | /*---------------------------------------------------------------------------*/ 159 | -------------------------------------------------------------------------------- /src/ui-keyboard.c: -------------------------------------------------------------------------------- 1 | #include "ui-keyboard.h" 2 | #include "ui.h" 3 | 4 | #include 5 | 6 | #include "util.h" 7 | 8 | uint8_t shift = 0; 9 | uint8_t alpha = 0; 10 | 11 | /* keycode_character(): Identify keys A .. Z, space and doublequotes */ 12 | int ui_keycode_character(int keycode) 13 | { 14 | // Non-Alpha Mode (0-9, etc.) 15 | if (alpha) 16 | { 17 | if (keycode >= KEY_7 && keycode <= KEY_9) 18 | return '7' + (keycode - KEY_7); 19 | 20 | if (keycode >= KEY_4 && keycode <= KEY_6) 21 | return '4' + (keycode - KEY_4); 22 | 23 | if (keycode >= KEY_1 && keycode <= KEY_3) 24 | return '1' + (keycode - KEY_1); 25 | 26 | if (keycode == KEY_0) return '0'; 27 | if (keycode == KEY_DOT) return '.'; 28 | if (keycode == KEY_ADD) return '+'; 29 | if (keycode == KEY_SUB) return '-'; 30 | if (keycode == KEY_MUL) return '*'; 31 | if (keycode == KEY_DIV) return '/'; 32 | if (keycode == KEY_LEFTP) return '('; 33 | if (keycode == KEY_RIGHTP) return ')'; 34 | if (keycode == KEY_COMMA) return ','; 35 | 36 | return -1; 37 | } 38 | 39 | uint8_t character = 0; 40 | 41 | if (keycode >= KEY_XOT && keycode <= KEY_TAN) 42 | character = 'A' + (keycode - KEY_XOT); 43 | 44 | if (keycode >= KEY_FRAC && keycode <= KEY_ARROW) 45 | character = 'G' + (keycode - KEY_FRAC); 46 | 47 | if (keycode >= KEY_7 && keycode <= KEY_9) 48 | character = 'M' + (keycode - KEY_7); 49 | 50 | if (keycode >= KEY_4 && keycode <= KEY_DIV) 51 | character = 'P' + (keycode - KEY_4); 52 | 53 | if (keycode >= KEY_1 && keycode <= KEY_SUB) 54 | character = 'U' + (keycode - KEY_1); 55 | 56 | if (keycode == KEY_0) character = 'Z'; 57 | if (keycode == KEY_DOT) character = ' '; 58 | if (keycode == KEY_EXP) character = '"'; 59 | 60 | if (!shift) 61 | { 62 | if (character >= 'A' && character <= 'Z') 63 | { 64 | return character + ('a' - 'A'); 65 | } 66 | } 67 | 68 | if (character) 69 | { 70 | return character; 71 | } 72 | 73 | return -1; 74 | } 75 | 76 | int ui_handle_keyboard() 77 | { 78 | // keyboard input 79 | uint8_t ui_needs_update = 0; 80 | 81 | int character = -1; 82 | key_event_t event = pollevent(); 83 | if (event.type == KEYEV_DOWN) 84 | { 85 | // Modifiers 86 | if (event.key == KEY_SHIFT) 87 | { 88 | shift = 1; 89 | } 90 | if (event.key == KEY_ALPHA) 91 | { 92 | alpha = 1; 93 | } 94 | } 95 | if (event.type == KEYEV_UP) 96 | { 97 | // Modifiers 98 | if (event.key == KEY_SHIFT) 99 | { 100 | shift = 0; 101 | } 102 | if (event.key == KEY_ALPHA) 103 | { 104 | alpha = 0; 105 | } 106 | 107 | // Page selection 108 | for (unsigned int pageid = 0; pageid < ARRAY_SIZE(pages); pageid++) 109 | { 110 | if (pages[pageid].key == event.key) 111 | { 112 | current_page = &pages[pageid]; 113 | ui_needs_update = 1; 114 | } 115 | } 116 | 117 | if (event.key == KEY_EXIT) 118 | { 119 | return -1; 120 | } 121 | 122 | if (current_page->input_enabled) 123 | { 124 | // horizontal scrolling in the input line 125 | if (event.key == KEY_LEFT) 126 | { 127 | if (current_page->input_scroll_offset) 128 | { 129 | current_page->input_scroll_offset--; 130 | } 131 | } 132 | if (event.key == KEY_RIGHT) 133 | { 134 | if (current_page->input_offset > UI_DISPLAY_CHARS) 135 | { 136 | if (current_page->input_scroll_offset < current_page->input_offset - UI_DISPLAY_CHARS) 137 | { 138 | current_page->input_scroll_offset++; 139 | } 140 | } 141 | } 142 | 143 | // Text input 144 | if ((character = ui_keycode_character(event.key)) >= 0) 145 | { 146 | // input buffer not full 147 | if (current_page->input_offset <= current_page->input_buffer_size - 2) 148 | { 149 | current_page->input_buffer[current_page->input_offset] = character; 150 | current_page->input_offset++; 151 | 152 | if (current_page->input_offset > UI_DISPLAY_CHARS) 153 | { 154 | current_page->input_scroll_offset = current_page->input_offset - UI_DISPLAY_CHARS; 155 | } 156 | } 157 | } 158 | if (event.key == KEY_DEL) 159 | { 160 | if (current_page->input_offset) 161 | { 162 | current_page->input_buffer[current_page->input_offset - 1] = 0x00; 163 | current_page->input_offset--; 164 | 165 | if (current_page->input_scroll_offset) 166 | { 167 | if (current_page->input_offset > UI_DISPLAY_CHARS) 168 | { 169 | current_page->input_scroll_offset = current_page->input_offset - UI_DISPLAY_CHARS; 170 | } 171 | else 172 | { 173 | current_page->input_scroll_offset = 0; 174 | } 175 | } 176 | } 177 | } 178 | if (event.key == KEY_EXE) 179 | { 180 | if (current_page->input_offset) 181 | { 182 | current_page->input_buffer[current_page->input_offset] = 0x00; 183 | current_page->input_submit_callback(current_page); 184 | memset(current_page->input_buffer, 0x00, current_page->input_offset); 185 | current_page->input_offset = 0; 186 | current_page->input_scroll_offset = 0; 187 | } 188 | } 189 | ui_needs_update = 1; 190 | } 191 | 192 | // if input is disabled or there is no text in the buffer, scroll the displayed window 193 | if (!current_page->input_enabled || current_page->input_offset == 0) 194 | { 195 | // horizontal scrolling in the buffer 196 | if (event.key == KEY_LEFT) 197 | { 198 | if (current_page->scroll_x) 199 | { 200 | current_page->scroll_x--; 201 | } 202 | } 203 | if (event.key == KEY_RIGHT) 204 | { 205 | current_page->scroll_x++; 206 | } 207 | 208 | ui_needs_update = 1; 209 | } 210 | 211 | } 212 | 213 | if (ui_needs_update) 214 | { 215 | ui_update(); 216 | } 217 | return 0; 218 | } 219 | -------------------------------------------------------------------------------- /src/uip/irc.c: -------------------------------------------------------------------------------- 1 | #include "irc.h" 2 | 3 | #include "psock.h" 4 | #include "uip.h" 5 | #include "ui.h" 6 | #include "util.h" 7 | 8 | #include 9 | 10 | #define _GNU_SOURCE 11 | #include "fxlibc/string.h" 12 | 13 | static char *localhostname; 14 | 15 | static const char irc_command_privmsg[] = "PRIVMSG"; 16 | static const char irc_command_error[] = "ERROR"; 17 | static const char irc_command_ping[] = "PING"; 18 | static const char irc_command_join[] = "JOIN"; 19 | 20 | const char irc_username[] = "CasioFXIRC"; 21 | int irc_username_length = 10; 22 | 23 | static int irc_parse_command(irc_message message) 24 | { 25 | char *whitespace; 26 | 27 | if (!strlen(message.command)) 28 | { 29 | ui_write_log(PAGE_IRC_OVERVIEW, 0, 0, "empty cmd", 11); 30 | return; 31 | } 32 | 33 | if (strncasecmp(message.command, irc_command_privmsg, strlen(message.command)) == 0) 34 | { 35 | whitespace = memchr(message.command_arguments, ' ', strlen(message.command_arguments)); 36 | if (whitespace == NULL) 37 | return; 38 | 39 | whitespace[2 + strlen(&whitespace[2]) - 1] = 0x00; 40 | 41 | // find ! in prefix (which contains the username) and end the string there 42 | char *prefixend = memchr(message.prefix, '!', strlen(message.prefix)); 43 | prefixend[0] = 0x00; 44 | 45 | printflength = snprintf(messagebuffer, sizeof(messagebuffer) - 1, "<%s> %s", message.prefix , &whitespace[2]); 46 | printflength = MIN(sizeof(messagebuffer), printflength); 47 | 48 | ui_write_log(PAGE_IRC_CHANNEL, 0, 0, messagebuffer, printflength); 49 | return; 50 | } 51 | 52 | if (strncasecmp(message.command, irc_command_ping, strlen(message.command)) == 0) 53 | { 54 | messagelength = snprintf(messagebuffer, sizeof(messagebuffer) - 1, "PONG %s", message.command_arguments); 55 | messagelength = MIN(sizeof(messagebuffer), messagelength); 56 | return; 57 | } 58 | 59 | if (strncasecmp(message.command, irc_command_join, strlen(message.command)) == 0) 60 | { 61 | ui_write_log(PAGE_IRC_OVERVIEW, 0, 0, "JOIN successful", 15); 62 | return; 63 | } 64 | 65 | whitespace = memchr(message.command_arguments, ' ', strlen(message.command_arguments)); 66 | if (whitespace == NULL) 67 | return; 68 | 69 | whitespace[2 + strlen(&whitespace[2]) - 1] = 0x00; 70 | ui_write_log(PAGE_IRC_OVERVIEW, 0, 0, &whitespace[2], strlen(&whitespace[2]) - 1); 71 | } 72 | 73 | static int irc_parse_line(char *data, uint16_t length) 74 | { 75 | char *whitespace; 76 | 77 | data[length - 1] = 0x00; 78 | 79 | irc_message message; 80 | message.message = data; 81 | message.length = length; 82 | message.prefix = NULL; 83 | message.message_without_prefix = NULL; 84 | message.command = NULL; 85 | message.command_arguments = NULL; 86 | 87 | // Prefix present? 88 | if (data[0] == ':') 89 | { 90 | whitespace = memchr(data, ' ', length); 91 | if (whitespace == NULL) 92 | { 93 | ui_write_log(PAGE_IRC_OVERVIEW, 0, 0, "no ws found", 11); 94 | return; 95 | } 96 | 97 | message.prefix = &data[1]; 98 | whitespace[0] = 0x00; 99 | 100 | message.message_without_prefix = &whitespace[1]; 101 | } 102 | else 103 | { 104 | message.message_without_prefix = data; 105 | } 106 | 107 | // split message into command and command args 108 | whitespace = memchr(message.message_without_prefix, ' ', strlen(message.message_without_prefix)); 109 | if (whitespace == NULL) 110 | { 111 | ui_write_log(PAGE_IRC_OVERVIEW, 0, 0, "no ws found", 11); 112 | return; 113 | } 114 | message.command = &message.message_without_prefix[0]; 115 | whitespace[0] = 0x00; 116 | 117 | message.command_arguments = &whitespace[1]; 118 | 119 | irc_parse_command(message); 120 | } 121 | 122 | /*---------------------------------------------------------------------------*/ 123 | static int irc_thread(struct irc_state *s) 124 | { 125 | PSOCK_BEGIN(&s->psock); 126 | 127 | PSOCK_SEND_STR(&s->psock, "nick CasioFXIRC\r\n"); 128 | PSOCK_SEND_STR(&s->psock, "user CasioFXIRC 0 0 CasioFX\r\n"); 129 | PSOCK_READTO(&s->psock, '\n'); 130 | PSOCK_SEND_STR(&s->psock, "JOIN ##whitequark\r\n"); 131 | PSOCK_READTO(&s->psock, '\n'); 132 | 133 | 134 | while (1) 135 | { 136 | PSOCK_READTO(&s->psock, '\n'); 137 | irc_parse_line(s->psock.bufptr, PSOCK_DATALEN(&s->psock)); 138 | } 139 | 140 | PSOCK_END(&s->psock); 141 | } 142 | 143 | static int irc_send_thread(struct irc_state *s) 144 | { 145 | PSOCK_BEGIN(&s->psock_out); 146 | 147 | PSOCK_SEND(&s->psock_out, messagebuffer, messagelength); 148 | PSOCK_SEND_STR(&s->psock_out, "\r\n"); 149 | 150 | messagelength = 0; 151 | 152 | PSOCK_END(&s->psock_out); 153 | } 154 | 155 | /*---------------------------------------------------------------------------*/ 156 | 157 | void irc_appcall(void) 158 | { 159 | struct irc_state *s = &(uip_conn->appstate); 160 | 161 | if (&s->psock == NULL || &s->psock_out == NULL) 162 | { 163 | return; 164 | } 165 | if(uip_closed()) 166 | { 167 | s->connected = 0; 168 | return; 169 | } 170 | if(uip_aborted() || uip_timedout()) 171 | { 172 | s->connected = 0; 173 | return; 174 | } 175 | 176 | irc_thread(&(uip_conn->appstate)); 177 | 178 | if (messagelength) 179 | { 180 | irc_send_thread(&(uip_conn->appstate)); 181 | } 182 | } 183 | 184 | unsigned char irc_connect(u16_t *server) 185 | { 186 | struct uip_conn *conn; 187 | 188 | conn = uip_connect(server, HTONS(6667)); 189 | if(conn == NULL) { 190 | return 0; 191 | } 192 | 193 | struct irc_state *s = &conn->appstate; 194 | messagelength = 0; 195 | s->connected = 1; 196 | s->connection_state = IRC_CONNECTION_NEW; 197 | 198 | PSOCK_INIT(&s->psock, s->inputbuffer, 1024); 199 | PSOCK_INIT(&s->psock_out, s->inputbuffer, 1024); 200 | 201 | return 1; 202 | } 203 | /*---------------------------------------------------------------------------*/ 204 | void 205 | irc_init(void) 206 | { 207 | } 208 | /*---------------------------------------------------------------------------*/ 209 | /** @} */ 210 | /** @} */ -------------------------------------------------------------------------------- /src/uip/uip-fw.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup uipfw 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \file 8 | * uIP packet forwarding header file. 9 | * \author Adam Dunkels 10 | */ 11 | 12 | /* 13 | * Copyright (c) 2004, Swedish Institute of Computer Science. 14 | * All rights reserved. 15 | * 16 | * Redistribution and use in source and binary forms, with or without 17 | * modification, are permitted provided that the following conditions 18 | * are met: 19 | * 1. Redistributions of source code must retain the above copyright 20 | * notice, this list of conditions and the following disclaimer. 21 | * 2. Redistributions in binary form must reproduce the above copyright 22 | * notice, this list of conditions and the following disclaimer in the 23 | * documentation and/or other materials provided with the distribution. 24 | * 3. Neither the name of the Institute nor the names of its contributors 25 | * may be used to endorse or promote products derived from this software 26 | * without specific prior written permission. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 29 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 | * SUCH DAMAGE. 39 | * 40 | * This file is part of the uIP TCP/IP stack 41 | * 42 | * Author: Adam Dunkels 43 | * 44 | * $Id: uip-fw.h,v 1.2 2006/06/12 08:00:30 adam Exp $ 45 | */ 46 | #ifndef __UIP_FW_H__ 47 | #define __UIP_FW_H__ 48 | 49 | #include "uip.h" 50 | 51 | /** 52 | * Representation of a uIP network interface. 53 | */ 54 | struct uip_fw_netif { 55 | struct uip_fw_netif *next; /**< Pointer to the next interface when 56 | linked in a list. */ 57 | u16_t ipaddr[2]; /**< The IP address of this interface. */ 58 | u16_t netmask[2]; /**< The netmask of the interface. */ 59 | u8_t (* output)(void); 60 | /**< A pointer to the function that 61 | sends a packet. */ 62 | }; 63 | 64 | /** 65 | * Intantiating macro for a uIP network interface. 66 | * 67 | * Example: 68 | \code 69 | struct uip_fw_netif slipnetif = 70 | {UIP_FW_NETIF(192,168,76,1, 255,255,255,0, slip_output)}; 71 | \endcode 72 | * \param ip1,ip2,ip3,ip4 The IP address of the network interface. 73 | * 74 | * \param nm1,nm2,nm3,nm4 The netmask of the network interface. 75 | * 76 | * \param outputfunc A pointer to the output function of the network interface. 77 | * 78 | * \hideinitializer 79 | */ 80 | #define UIP_FW_NETIF(ip1,ip2,ip3,ip4, nm1,nm2,nm3,nm4, outputfunc) \ 81 | NULL, \ 82 | {HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \ 83 | {HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \ 84 | outputfunc 85 | 86 | /** 87 | * Set the IP address of a network interface. 88 | * 89 | * \param netif A pointer to the uip_fw_netif structure for the network interface. 90 | * 91 | * \param addr A pointer to an IP address. 92 | * 93 | * \hideinitializer 94 | */ 95 | #define uip_fw_setipaddr(netif, addr) \ 96 | do { (netif)->ipaddr[0] = ((u16_t *)(addr))[0]; \ 97 | (netif)->ipaddr[1] = ((u16_t *)(addr))[1]; } while(0) 98 | /** 99 | * Set the netmask of a network interface. 100 | * 101 | * \param netif A pointer to the uip_fw_netif structure for the network interface. 102 | * 103 | * \param addr A pointer to an IP address representing the netmask. 104 | * 105 | * \hideinitializer 106 | */ 107 | #define uip_fw_setnetmask(netif, addr) \ 108 | do { (netif)->netmask[0] = ((u16_t *)(addr))[0]; \ 109 | (netif)->netmask[1] = ((u16_t *)(addr))[1]; } while(0) 110 | 111 | void uip_fw_init(void); 112 | u8_t uip_fw_forward(void); 113 | u8_t uip_fw_output(void); 114 | void uip_fw_register(struct uip_fw_netif *netif); 115 | void uip_fw_default(struct uip_fw_netif *netif); 116 | void uip_fw_periodic(void); 117 | 118 | 119 | /** 120 | * A non-error message that indicates that a packet should be 121 | * processed locally. 122 | * 123 | * \hideinitializer 124 | */ 125 | #define UIP_FW_LOCAL 0 126 | 127 | /** 128 | * A non-error message that indicates that something went OK. 129 | * 130 | * \hideinitializer 131 | */ 132 | #define UIP_FW_OK 0 133 | 134 | /** 135 | * A non-error message that indicates that a packet was forwarded. 136 | * 137 | * \hideinitializer 138 | */ 139 | #define UIP_FW_FORWARDED 1 140 | 141 | /** 142 | * A non-error message that indicates that a zero-length packet 143 | * transmission was attempted, and that no packet was sent. 144 | * 145 | * \hideinitializer 146 | */ 147 | #define UIP_FW_ZEROLEN 2 148 | 149 | /** 150 | * An error message that indicates that a packet that was too large 151 | * for the outbound network interface was detected. 152 | * 153 | * \hideinitializer 154 | */ 155 | #define UIP_FW_TOOLARGE 3 156 | 157 | /** 158 | * An error message that indicates that no suitable interface could be 159 | * found for an outbound packet. 160 | * 161 | * \hideinitializer 162 | */ 163 | #define UIP_FW_NOROUTE 4 164 | 165 | /** 166 | * An error message that indicates that a packet that should be 167 | * forwarded or output was dropped. 168 | * 169 | * \hideinitializer 170 | */ 171 | #define UIP_FW_DROPPED 5 172 | 173 | 174 | #endif /* __UIP_FW_H__ */ 175 | 176 | /** @} */ 177 | -------------------------------------------------------------------------------- /src/ui.c: -------------------------------------------------------------------------------- 1 | #include "ui.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "util.h" 10 | #include "log.h" 11 | #include "uip/uip.h" 12 | #include "uip/irc.h" 13 | 14 | extern struct uip_stats uip_stat; 15 | extern const char irc_username[]; 16 | 17 | uint8_t cursor_blink = 0; 18 | 19 | char page_irc_channel_input_buffer[128]; 20 | uint8_t objectlog_storage[2048]; 21 | objectlog_t objectlog; 22 | 23 | void ui_cursor_blink() 24 | { 25 | cursor_blink = !cursor_blink; 26 | } 27 | 28 | void ui_page_irc_message_submit(page_t *page) 29 | { 30 | printflength = snprintf(messagebuffer, sizeof(messagebuffer) - 1, "<%s> %s", irc_username, page->input_buffer); 31 | printflength = MIN(sizeof(messagebuffer), printflength); 32 | ui_write_log(PAGE_IRC_CHANNEL, 0, 0, messagebuffer, printflength); 33 | 34 | messagelength = snprintf(messagebuffer, sizeof(messagebuffer), "PRIVMSG ##whitequark :%s", page->input_buffer); 35 | messagelength = MIN(sizeof(messagebuffer), messagelength); 36 | } 37 | 38 | const page_t pages[] = { 39 | { 40 | /* Logs */ 41 | .id = PAGE_LOGS, 42 | .key = KEY_F1, 43 | .render_callback = ui_render_logs, 44 | .input_enabled = 0, 45 | }, 46 | { 47 | /* Statistics */ 48 | .id = PAGE_STATISTICS, 49 | .key = KEY_F2, 50 | .render_callback = ui_render_statistics, 51 | .input_enabled = 0 52 | }, 53 | { 54 | /* IRC Overview */ 55 | .id = PAGE_IRC_OVERVIEW, 56 | .key = KEY_F3, 57 | .render_callback = ui_render_logs, 58 | .input_enabled = 0 59 | }, 60 | { 61 | /* IRC Channel */ 62 | .id = PAGE_IRC_CHANNEL, 63 | .key = KEY_F4, 64 | .render_callback = ui_render_logs, 65 | .input_enabled = 1, 66 | .input_buffer = page_irc_channel_input_buffer, 67 | .input_buffer_size = sizeof(page_irc_channel_input_buffer), 68 | .input_submit_callback = ui_page_irc_message_submit 69 | }, 70 | }; 71 | 72 | page_t *current_page = &pages[0]; 73 | 74 | 75 | void ui_update() 76 | { 77 | dclear(C_WHITE); 78 | current_page->render_callback(current_page); 79 | if (current_page->input_enabled) 80 | { 81 | drect(0, 55, 128, 64, C_BLACK); 82 | 83 | char *scrolled_input = current_page->input_buffer; 84 | if (current_page->input_offset > UI_DISPLAY_CHARS) 85 | { 86 | scrolled_input += MIN(current_page->input_scroll_offset, 87 | current_page->input_offset - UI_DISPLAY_CHARS); 88 | } 89 | uint16_t scrolled_input_length = strlen(scrolled_input); 90 | 91 | dtext_opt(1, 56, C_WHITE, C_NONE, DTEXT_LEFT, DTEXT_TOP, scrolled_input, scrolled_input_length); 92 | 93 | if (cursor_blink) 94 | { 95 | int width = 0; 96 | int height = 0; 97 | 98 | dnsize(scrolled_input, scrolled_input_length, NULL, &width, &height); 99 | 100 | dtext_opt(1 + width, 56, C_WHITE, C_NONE, DTEXT_LEFT, DTEXT_TOP, "_", 1); 101 | } 102 | 103 | } 104 | 105 | dupdate(); 106 | } 107 | 108 | void ui_update_logs() 109 | { 110 | if (current_page->id == 0) 111 | { 112 | ui_update(); 113 | } 114 | } 115 | 116 | void ui_render_logs(page_t *page) 117 | { 118 | uint16_t lines_drawn = 0; 119 | uint8_t max_lines = UI_DISPLAY_LINES; 120 | 121 | if (page->input_enabled) 122 | { 123 | max_lines--; 124 | } 125 | 126 | for (unsigned int i = 0; i < objectlog.num_entries && lines_drawn < max_lines; i++) 127 | { 128 | uint8_t pencil_x = 0; 129 | uint8_t pencil_y = (max_lines - lines_drawn) * 8; 130 | int width = 0; 131 | int height = 0; 132 | 133 | message_hdr_t hdr; 134 | hdr.page_id = 0xFF; 135 | uint8_t length; 136 | objectlog_iterator_t iter; 137 | const uint8_t *ptr; 138 | ptr = ui_objectlog_get_message(&objectlog, -i, page->scroll_x, &iter, &hdr, &length); 139 | 140 | if (hdr.page_id == page->id) 141 | { 142 | if (!ptr) 143 | { 144 | lines_drawn++; 145 | continue; 146 | } 147 | 148 | do { 149 | if (length) 150 | { 151 | dtext_opt(pencil_x, pencil_y, C_BLACK, C_NONE, DTEXT_LEFT, DTEXT_TOP, ptr, length); 152 | 153 | dnsize(ptr, length, NULL, &width, &height); 154 | pencil_x += width; 155 | if (pencil_x > UI_DISPLAY_PIXEL_X) 156 | { 157 | break; 158 | } 159 | } 160 | iter = objectlog_next(&objectlog, iter); 161 | ptr = objectlog_get_fragment(&objectlog, iter, &length); 162 | } while (iter >= 0); 163 | lines_drawn++; 164 | } 165 | } 166 | } 167 | 168 | const void *ui_objectlog_get_message(objectlog_t *log, int object_idx, unsigned offset, objectlog_iterator_t *riter, message_hdr_t *hdr, uint8_t *len) 169 | { 170 | uint8_t length; 171 | uint8_t bytes_read = 0; 172 | const uint8_t *ptr; 173 | objectlog_iterator_t iter = objectlog_iterator(log, object_idx); 174 | 175 | if (iter < 0) 176 | { 177 | return NULL; 178 | } 179 | 180 | do { 181 | ptr = objectlog_get_fragment(log, iter, &length); 182 | 183 | uint8_t cpylen = MIN(sizeof(message_hdr_t) - bytes_read, length); 184 | memcpy(((uint8_t*)hdr) + bytes_read, ptr, cpylen); 185 | bytes_read += cpylen; 186 | } while (bytes_read < sizeof(message_hdr_t)); 187 | 188 | length -= bytes_read; 189 | ptr += bytes_read; 190 | 191 | while (offset) 192 | { 193 | unsigned int read_len = length; 194 | 195 | if (read_len > offset) 196 | { 197 | read_len = offset; 198 | } 199 | 200 | ptr += read_len; 201 | offset -= read_len; 202 | length -= read_len; 203 | 204 | if (!length) 205 | { 206 | iter = objectlog_next(&objectlog, iter); 207 | 208 | if (iter <= 0) 209 | { 210 | return NULL; 211 | } 212 | 213 | ptr = objectlog_get_fragment(&objectlog, iter, &length); 214 | } 215 | } 216 | 217 | *riter = iter; 218 | *len = length; 219 | return ptr; 220 | } 221 | 222 | void ui_init() 223 | { 224 | for (unsigned int i = 0; i < ARRAY_SIZE(pages); i++) 225 | { 226 | if (pages[i].input_buffer) 227 | { 228 | memset(pages[i].input_buffer, 0x00, pages[i].input_buffer_size); 229 | } 230 | } 231 | 232 | objectlog_init(&objectlog, objectlog_storage, sizeof(objectlog_storage)); 233 | } 234 | 235 | void ui_write_log(uint8_t page_id, uint8_t type, uint8_t channel, char *data, uint16_t length) 236 | { 237 | message_hdr_t hdr; 238 | hdr.page_id = page_id; 239 | hdr.type = type; 240 | hdr.channel = channel; 241 | 242 | scatter_object_t scatter_list[] = { 243 | { .ptr = &hdr, .len = sizeof(hdr) }, 244 | { .ptr = data, .len = length }, 245 | { .len = 0 } 246 | }; 247 | 248 | objectlog_write_scattered_object(&objectlog, scatter_list); 249 | } 250 | 251 | void ui_render_statistics(page_t *page) 252 | { 253 | ui_printf(0, 0, C_BLACK, "IP RX: %u TX: %u", uip_stat.ip.recv, uip_stat.ip.sent); 254 | ui_printf(20, 10, C_BLACK, "Dropped: %u", uip_stat.ip.drop); 255 | ui_printf(0, 23, C_BLACK, "ICMP RX: %u TX: %u", uip_stat.icmp.recv, uip_stat.icmp.sent); 256 | 257 | ui_printf(1, 35, C_BLACK, "TCP:"); 258 | ui_printf(10, 45, C_BLACK, "Chksum err: %u", uip_stat.tcp.chkerr); 259 | ui_printf(10, 55, C_BLACK, "Rexmit: %u", uip_stat.tcp.rexmit); 260 | } 261 | 262 | extern char printf_buffer[128]; 263 | void ui_printf(int x, int y, int fg, const char * format, ...) 264 | { 265 | va_list args; 266 | va_start (args, format); 267 | vsnprintf (printf_buffer, sizeof(printf_buffer), format, args); 268 | dtext(x, y, fg, printf_buffer); 269 | va_end (args); 270 | } 271 | 272 | -------------------------------------------------------------------------------- /src/slipdev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Adam Dunkels. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote 14 | * products derived from this software without specific prior 15 | * written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack. 30 | * 31 | * 32 | */ 33 | 34 | /** 35 | * \file 36 | * SLIP protocol implementation 37 | * \author Adam Dunkels 38 | */ 39 | 40 | /** 41 | * \addtogroup uip 42 | * @{ 43 | */ 44 | 45 | /** 46 | * \defgroup slip Serial Line IP (SLIP) protocol 47 | * @{ 48 | * 49 | * The SLIP protocol is a very simple way to transmit IP packets over 50 | * a serial line. It does not provide any framing or error control, 51 | * and is therefore not very widely used today. 52 | * 53 | * This SLIP implementation requires two functions for accessing the 54 | * serial device: slipdev_char_poll() and slipdev_char_put(). These 55 | * must be implemented specifically for the system on which the SLIP 56 | * protocol is to be run. 57 | */ 58 | 59 | /* 60 | * This is a generic implementation of the SLIP protocol over an RS232 61 | * (serial) device. 62 | * 63 | * Huge thanks to Ullrich von Bassewitz of cc65 fame for 64 | * and endless supply of bugfixes, insightsful comments and 65 | * suggestions, and improvements to this code! 66 | */ 67 | 68 | #include "slipdev.h" 69 | #include /* For memcpy() */ 70 | #include "uip/uip.h" 71 | #include "scif.h" 72 | 73 | #define SLIP_END 0xC0 74 | #define SLIP_ESC 0xDB 75 | #define SLIP_ESC_END 0xDC 76 | #define SLIP_ESC_ESC 0xDD 77 | 78 | static uint8_t slip_buf[UIP_BUFSIZE]; 79 | 80 | static uint16_t len, tmplen; 81 | static uint8_t lastc; 82 | 83 | /** 84 | * Put a character on the serial device. 85 | * 86 | * This function is used by the SLIP implementation to put a character 87 | * on the serial device. It must be implemented specifically for the 88 | * system on which the SLIP implementation is to be run. 89 | * 90 | * \param c The character to be put on the serial device. 91 | */ 92 | static void slipdev_char_put(uint8_t c) 93 | { 94 | scif_write(&c, 1); 95 | } 96 | 97 | /** 98 | * Poll the serial device for a character. 99 | * 100 | * This function is used by the SLIP implementation to poll the serial 101 | * device for a character. It must be implemented specifically for the 102 | * system on which the SLIP implementation is to be run. 103 | * 104 | * The function should return immediately regardless if a character is 105 | * available or not. If a character is available it should be placed 106 | * at the memory location pointed to by the pointer supplied by the 107 | * argument c. 108 | * 109 | * \param c A pointer to a byte that is filled in by the function with 110 | * the received character, if available. 111 | * 112 | * \retval 0 If no character is available. 113 | * \retval Non-zero If a character is available. 114 | */ 115 | static int slipdev_char_poll(uint8_t *c) 116 | { 117 | int data = scif_read(); 118 | if (data < 0) 119 | return 0; 120 | 121 | *c = data; 122 | return 1; 123 | } 124 | 125 | /*-----------------------------------------------------------------------------------*/ 126 | /** 127 | * Send the packet in the uip_buf and uip_appdata buffers using the 128 | * SLIP protocol. 129 | * 130 | * The first 40 bytes of the packet (the IP and TCP headers) are read 131 | * from the uip_buf buffer, and the following bytes (the application 132 | * data) are read from the uip_appdata buffer. 133 | * 134 | * \return This function will always return 0. 135 | */ 136 | /*-----------------------------------------------------------------------------------*/ 137 | uint8_t slipdev_send(void) 138 | { 139 | uint16_t i; 140 | uint8_t *ptr; 141 | uint8_t c; 142 | 143 | slipdev_char_put(SLIP_END); 144 | 145 | ptr = &uip_buf[UIP_LLH_LEN]; 146 | for(i = 0; i < uip_len; ++i) { 147 | c = *ptr++; 148 | switch(c) { 149 | case SLIP_END: 150 | slipdev_char_put(SLIP_ESC); 151 | slipdev_char_put(SLIP_ESC_END); 152 | break; 153 | case SLIP_ESC: 154 | slipdev_char_put(SLIP_ESC); 155 | slipdev_char_put(SLIP_ESC_ESC); 156 | break; 157 | default: 158 | slipdev_char_put(c); 159 | break; 160 | } 161 | } 162 | slipdev_char_put(SLIP_END); 163 | 164 | return 0; 165 | } 166 | 167 | 168 | 169 | /*-----------------------------------------------------------------------------------*/ 170 | /** 171 | * Poll the SLIP device for an available packet. 172 | * 173 | * This function will poll the SLIP device to see if a packet is 174 | * available. It uses a buffer in which all avaliable bytes from the 175 | * RS232 interface are read into. When a full packet has been read 176 | * into the buffer, the packet is copied into the uip_buf buffer and 177 | * the length of the packet is returned. 178 | * 179 | * \return The length of the packet placed in the uip_buf buffer, or 180 | * zero if no packet is available. 181 | */ 182 | /*-----------------------------------------------------------------------------------*/ 183 | uint16_t slipdev_poll(void) 184 | { 185 | uint8_t c; 186 | 187 | while(slipdev_char_poll(&c)) { 188 | switch(c) { 189 | case SLIP_ESC: 190 | lastc = c; 191 | break; 192 | 193 | case SLIP_END: 194 | lastc = c; 195 | /* End marker found, we copy our input buffer to the uip_buf 196 | buffer and return the size of the packet we copied. */ 197 | memcpy(&uip_buf[UIP_LLH_LEN], slip_buf, len); 198 | 199 | tmplen = len; 200 | len = 0; 201 | return tmplen; 202 | 203 | default: 204 | if(lastc == SLIP_ESC) { 205 | lastc = c; 206 | /* Previous read byte was an escape byte, so this byte will be 207 | interpreted differently from others. */ 208 | switch(c) { 209 | case SLIP_ESC_END: 210 | c = SLIP_END; 211 | break; 212 | case SLIP_ESC_ESC: 213 | c = SLIP_ESC; 214 | break; 215 | } 216 | } else { 217 | lastc = c; 218 | } 219 | 220 | slip_buf[len] = c; 221 | ++len; 222 | 223 | if(len > UIP_BUFSIZE) { 224 | len = 0; 225 | } 226 | 227 | break; 228 | } 229 | } 230 | return 0; 231 | } 232 | /*-----------------------------------------------------------------------------------*/ 233 | /** 234 | * Initialize the SLIP module. 235 | * 236 | * This function does not initialize the underlying RS232 device, but 237 | * only the SLIP part. 238 | */ 239 | /*-----------------------------------------------------------------------------------*/ 240 | void slipdev_init(void) 241 | { 242 | lastc = len = 0; 243 | } 244 | /*-----------------------------------------------------------------------------------*/ 245 | 246 | /** @} */ 247 | /** @} */ 248 | -------------------------------------------------------------------------------- /src/objectlog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "objectlog.h" 5 | 6 | #define MAX_FRAGMENT_LEN 0x7f 7 | #define FRAGMENT_FINAL 0x80 8 | #define FRAGMENT_LEN(x) ((x)&MAX_FRAGMENT_LEN) 9 | 10 | #define DIV_ROUND_UP(x, y) (((x) + ((y)-1)) / (y)) 11 | 12 | static uint16_t get_next_entry(objectlog_t *log, uint16_t offset) 13 | { 14 | uint8_t fragment_hdr; 15 | 16 | log->ring.read_ptr = offset; 17 | do 18 | { 19 | uint16_t hdr_pos = log->ring.read_ptr; 20 | 21 | fragment_hdr = ringbuffer_read_one(&log->ring); 22 | ringbuffer_advance_read(&log->ring, FRAGMENT_LEN(fragment_hdr)); 23 | /* 24 | * There might be no terminating entry in the list. Detect 25 | * whether we have wrapped across @offset and terminate if 26 | * we did 27 | */ 28 | if ((hdr_pos < offset && log->ring.read_ptr >= offset) || 29 | (hdr_pos > offset && log->ring.read_ptr >= offset && 30 | log->ring.read_ptr < hdr_pos)) 31 | { 32 | return log->ptr_first; 33 | } 34 | } while (!(fragment_hdr & FRAGMENT_FINAL)); 35 | 36 | return log->ring.read_ptr; 37 | } 38 | 39 | static uint16_t objectlog_space_between(objectlog_t *log, uint16_t first, uint16_t second) 40 | { 41 | if (second >= first) 42 | { 43 | return second - first; 44 | } 45 | else 46 | { 47 | return log->ring.size - first + second; 48 | } 49 | } 50 | 51 | static uint16_t drop_first_entry(objectlog_t *log) 52 | { 53 | log->ptr_first = get_next_entry(log, log->ptr_first); 54 | log->num_entries--; 55 | return log->ptr_first; 56 | } 57 | 58 | static uint16_t objectlog_free_space(objectlog_t *log, uint16_t from) 59 | { 60 | return objectlog_space_between(log, from, log->ptr_first); 61 | } 62 | 63 | static void objectlog_write_fragment_hdr(objectlog_t *log, uint16_t len, bool final) 64 | { 65 | uint8_t hdr = FRAGMENT_LEN(len); 66 | 67 | if (final) 68 | { 69 | hdr |= FRAGMENT_FINAL; 70 | } 71 | ringbuffer_write_one(&log->ring, hdr); 72 | } 73 | 74 | static void objectlog_write_fragment_data(objectlog_t *log, const void *data, uint16_t len) 75 | { 76 | ringbuffer_write(&log->ring, data, len); 77 | } 78 | 79 | void objectlog_init(objectlog_t *log, void *storage, uint16_t size) 80 | { 81 | ringbuffer_init(&log->ring, storage, size); 82 | log->ptr_first = 0; 83 | log->ptr_last = 0; 84 | log->num_entries = 0; 85 | } 86 | 87 | /** 88 | * Write object from non-contuguous memory area to object log 89 | * Oftentimes data that needs to be stored is not available from a contiguous 90 | * memory region. This method accepts a list of (pointer, length) pairs and 91 | * constructs the object to be stored by iterating over it. In each iteration 92 | * @length bytes read from @pointer are appended to the object log. 93 | * 94 | * @returns: 0 on success, number of bytes missing for storage on failure 95 | */ 96 | uint16_t objectlog_write_scattered_object(objectlog_t *log, const scatter_object_t *scatter_list) 97 | { 98 | const scatter_object_t *sc_list = scatter_list; 99 | const uint8_t *data8; 100 | uint16_t num_fragments; 101 | uint16_t data_len = 0; 102 | uint16_t total_len; 103 | uint16_t new_last; 104 | uint16_t free_space; 105 | uint16_t log_end = get_next_entry(log, log->ptr_last); 106 | uint16_t scatter_entry_offset = 0; 107 | uint16_t fragment_offset = 0; 108 | uint16_t fragment_len; 109 | 110 | /* Calculate total length of all data in @scatter_list */ 111 | while (sc_list->len) 112 | { 113 | data_len += sc_list++->len; 114 | } 115 | 116 | /* Calculate number of fragments required to store data */ 117 | num_fragments = DIV_ROUND_UP(data_len, MAX_FRAGMENT_LEN); 118 | total_len = data_len + num_fragments; 119 | /* Special case: If we wrap we need an extra header! */ 120 | if (log_end + total_len > log->ring.size) 121 | { 122 | total_len++; 123 | } 124 | /* We can not store any messages exceeding size of this buffer */ 125 | if (total_len > log->ring.size) 126 | { 127 | return log->ring.size - total_len; 128 | } 129 | 130 | /* Get number of bytes not in use at the moment */ 131 | free_space = objectlog_free_space(log, log_end); 132 | /* Delete entries from start of list until object fits */ 133 | while (free_space < total_len && log->ptr_first != log->ptr_last) 134 | { 135 | drop_first_entry(log); 136 | free_space = objectlog_free_space(log, log_end); 137 | } 138 | 139 | /* Store start of object header */ 140 | new_last = log->ring.write_ptr; 141 | 142 | /* Write object as @num_fragments fragments */ 143 | sc_list = scatter_list; 144 | data8 = sc_list->ptr; 145 | while (sc_list->len) 146 | { 147 | uint16_t write_len = data_len; 148 | 149 | /* Calculate maximum permissible size for this fragment */ 150 | if (!fragment_offset) 151 | { 152 | fragment_len = MAX_FRAGMENT_LEN; 153 | /* Ensure fragment does not wrap in ring buffer */ 154 | if (fragment_len > log->ring.size - log->ring.write_ptr - 1) 155 | { 156 | fragment_len = log->ring.size - log->ring.write_ptr - 1; 157 | } 158 | } 159 | 160 | /* Limit write size to fragment length */ 161 | if (write_len + fragment_offset > fragment_len) 162 | { 163 | write_len = fragment_len - fragment_offset; 164 | } 165 | 166 | /* Write fragment header whenever we start a new fragment */ 167 | if (!fragment_offset) 168 | { 169 | objectlog_write_fragment_hdr(log, write_len, data_len == write_len); 170 | } 171 | 172 | /* Limit length of this write to scatter entry length */ 173 | if (write_len > sc_list->len - scatter_entry_offset) 174 | { 175 | write_len = sc_list->len - scatter_entry_offset; 176 | } 177 | 178 | objectlog_write_fragment_data(log, data8, write_len); 179 | data8 += write_len; 180 | data_len -= write_len; 181 | scatter_entry_offset += write_len; 182 | fragment_offset += write_len; 183 | 184 | /* Switch to next scatter entry if there is no more data in current one */ 185 | if (scatter_entry_offset >= sc_list->len) 186 | { 187 | sc_list++; 188 | data8 = sc_list->ptr; 189 | scatter_entry_offset = 0; 190 | } 191 | /* Start new fragment if there is no more space in current one */ 192 | if (fragment_offset >= fragment_len) 193 | { 194 | fragment_offset = 0; 195 | } 196 | } 197 | log->ptr_last = new_last; 198 | log->num_entries++; 199 | 200 | return 0; 201 | } 202 | 203 | uint16_t objectlog_write_object(objectlog_t *log, const void *data, uint16_t len) 204 | { 205 | scatter_object_t scatter_list[] = { 206 | {.ptr = data, .len = len}, 207 | {.len = 0}}; 208 | 209 | return objectlog_write_scattered_object(log, scatter_list); 210 | } 211 | 212 | uint16_t objectlog_write_string(objectlog_t *log, const char *str) 213 | { 214 | return objectlog_write_object(log, str, strlen(str)); 215 | } 216 | 217 | /** 218 | * Obtain interator for object at index @object_idx 219 | * Negative indices count from last to first string. 220 | * 221 | * @returns: non-negative iterator value on success, -1 on failure 222 | */ 223 | objectlog_iterator_t objectlog_iterator(objectlog_t *log, int object_idx) 224 | { 225 | uint16_t string_ptr = log->ptr_first; 226 | 227 | if (object_idx < 0) 228 | { 229 | object_idx = -object_idx; 230 | if (object_idx >= log->num_entries) 231 | { 232 | return -1; 233 | } 234 | object_idx = log->num_entries - object_idx; 235 | } 236 | else 237 | { 238 | if (object_idx >= log->num_entries) 239 | { 240 | return -1; 241 | } 242 | } 243 | 244 | while (object_idx--) 245 | { 246 | string_ptr = get_next_entry(log, string_ptr); 247 | } 248 | 249 | return string_ptr; 250 | } 251 | 252 | /** 253 | * Get current iteration fragment 254 | * 255 | * @returns: non-NULL pointer to data on success, NULL on failure 256 | */ 257 | const void *objectlog_get_fragment(objectlog_t *log, objectlog_iterator_t iterator, uint8_t *len) 258 | { 259 | if (iterator < 0) 260 | { 261 | return NULL; 262 | } 263 | 264 | if (iterator > log->ring.size) 265 | { 266 | return NULL; 267 | } 268 | 269 | *len = FRAGMENT_LEN(log->ring.buffer[iterator]); 270 | return &log->ring.buffer[iterator + 1]; 271 | } 272 | 273 | /** 274 | * Advance iterator to next fragment 275 | * 276 | * @returns: -2 if there are no more fragments or 277 | * non-negative iterator value of next fragment or 278 | * -1 on failure 279 | */ 280 | objectlog_iterator_t objectlog_next(objectlog_t *log, objectlog_iterator_t iterator) 281 | { 282 | uint16_t len; 283 | 284 | if (iterator < 0) 285 | { 286 | return -1; 287 | } 288 | 289 | if (iterator > log->ring.size) 290 | { 291 | return -1; 292 | } 293 | 294 | len = FRAGMENT_LEN(log->ring.buffer[iterator]); 295 | if (log->ring.buffer[iterator] & FRAGMENT_FINAL) 296 | { 297 | return -2; 298 | } 299 | 300 | iterator++; 301 | iterator += len; 302 | iterator %= log->ring.size; 303 | return iterator; 304 | } 305 | 306 | /** 307 | * Get size of object at index @object_idx 308 | * 309 | * @returns: -1 on failure, else 310 | * non-negative length of object 311 | */ 312 | long objectlog_get_object_size(objectlog_t *log, int object_idx) 313 | { 314 | objectlog_iterator_t iter; 315 | uint16_t len = 0; 316 | 317 | iter = objectlog_iterator(log, object_idx); 318 | if (iter < 0) 319 | { 320 | return -1; 321 | } 322 | while (iter >= 0) 323 | { 324 | uint8_t fragment_size; 325 | 326 | if (!objectlog_get_fragment(log, iter, &fragment_size)) 327 | { 328 | return -1; 329 | } 330 | len += fragment_size; 331 | iter = objectlog_next(log, iter); 332 | } 333 | 334 | return len; 335 | } -------------------------------------------------------------------------------- /src/uip/pt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004-2005, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: pt.h,v 1.2 2006/06/12 08:00:30 adam Exp $ 34 | */ 35 | 36 | /** 37 | * \addtogroup pt 38 | * @{ 39 | */ 40 | 41 | /** 42 | * \file 43 | * Protothreads implementation. 44 | * \author 45 | * Adam Dunkels 46 | * 47 | */ 48 | 49 | #ifndef __PT_H__ 50 | #define __PT_H__ 51 | 52 | #include "lc.h" 53 | 54 | struct pt { 55 | lc_t lc; 56 | }; 57 | 58 | #define PT_WAITING 0 59 | #define PT_EXITED 1 60 | #define PT_ENDED 2 61 | #define PT_YIELDED 3 62 | 63 | /** 64 | * \name Initialization 65 | * @{ 66 | */ 67 | 68 | /** 69 | * Initialize a protothread. 70 | * 71 | * Initializes a protothread. Initialization must be done prior to 72 | * starting to execute the protothread. 73 | * 74 | * \param pt A pointer to the protothread control structure. 75 | * 76 | * \sa PT_SPAWN() 77 | * 78 | * \hideinitializer 79 | */ 80 | #define PT_INIT(pt) LC_INIT((pt)->lc) 81 | 82 | /** @} */ 83 | 84 | /** 85 | * \name Declaration and definition 86 | * @{ 87 | */ 88 | 89 | /** 90 | * Declaration of a protothread. 91 | * 92 | * This macro is used to declare a protothread. All protothreads must 93 | * be declared with this macro. 94 | * 95 | * \param name_args The name and arguments of the C function 96 | * implementing the protothread. 97 | * 98 | * \hideinitializer 99 | */ 100 | #define PT_THREAD(name_args) char name_args 101 | 102 | /** 103 | * Declare the start of a protothread inside the C function 104 | * implementing the protothread. 105 | * 106 | * This macro is used to declare the starting point of a 107 | * protothread. It should be placed at the start of the function in 108 | * which the protothread runs. All C statements above the PT_BEGIN() 109 | * invokation will be executed each time the protothread is scheduled. 110 | * 111 | * \param pt A pointer to the protothread control structure. 112 | * 113 | * \hideinitializer 114 | */ 115 | #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc) 116 | 117 | /** 118 | * Declare the end of a protothread. 119 | * 120 | * This macro is used for declaring that a protothread ends. It must 121 | * always be used together with a matching PT_BEGIN() macro. 122 | * 123 | * \param pt A pointer to the protothread control structure. 124 | * 125 | * \hideinitializer 126 | */ 127 | #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \ 128 | PT_INIT(pt); return PT_ENDED; } 129 | 130 | /** @} */ 131 | 132 | /** 133 | * \name Blocked wait 134 | * @{ 135 | */ 136 | 137 | /** 138 | * Block and wait until condition is true. 139 | * 140 | * This macro blocks the protothread until the specified condition is 141 | * true. 142 | * 143 | * \param pt A pointer to the protothread control structure. 144 | * \param condition The condition. 145 | * 146 | * \hideinitializer 147 | */ 148 | #define PT_WAIT_UNTIL(pt, condition) \ 149 | do { \ 150 | LC_SET((pt)->lc); \ 151 | if(!(condition)) { \ 152 | return PT_WAITING; \ 153 | } \ 154 | } while(0) 155 | 156 | /** 157 | * Block and wait while condition is true. 158 | * 159 | * This function blocks and waits while condition is true. See 160 | * PT_WAIT_UNTIL(). 161 | * 162 | * \param pt A pointer to the protothread control structure. 163 | * \param cond The condition. 164 | * 165 | * \hideinitializer 166 | */ 167 | #define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond)) 168 | 169 | /** @} */ 170 | 171 | /** 172 | * \name Hierarchical protothreads 173 | * @{ 174 | */ 175 | 176 | /** 177 | * Block and wait until a child protothread completes. 178 | * 179 | * This macro schedules a child protothread. The current protothread 180 | * will block until the child protothread completes. 181 | * 182 | * \note The child protothread must be manually initialized with the 183 | * PT_INIT() function before this function is used. 184 | * 185 | * \param pt A pointer to the protothread control structure. 186 | * \param thread The child protothread with arguments 187 | * 188 | * \sa PT_SPAWN() 189 | * 190 | * \hideinitializer 191 | */ 192 | #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread)) 193 | 194 | /** 195 | * Spawn a child protothread and wait until it exits. 196 | * 197 | * This macro spawns a child protothread and waits until it exits. The 198 | * macro can only be used within a protothread. 199 | * 200 | * \param pt A pointer to the protothread control structure. 201 | * \param child A pointer to the child protothread's control structure. 202 | * \param thread The child protothread with arguments 203 | * 204 | * \hideinitializer 205 | */ 206 | #define PT_SPAWN(pt, child, thread) \ 207 | do { \ 208 | PT_INIT((child)); \ 209 | PT_WAIT_THREAD((pt), (thread)); \ 210 | } while(0) 211 | 212 | /** @} */ 213 | 214 | /** 215 | * \name Exiting and restarting 216 | * @{ 217 | */ 218 | 219 | /** 220 | * Restart the protothread. 221 | * 222 | * This macro will block and cause the running protothread to restart 223 | * its execution at the place of the PT_BEGIN() call. 224 | * 225 | * \param pt A pointer to the protothread control structure. 226 | * 227 | * \hideinitializer 228 | */ 229 | #define PT_RESTART(pt) \ 230 | do { \ 231 | PT_INIT(pt); \ 232 | return PT_WAITING; \ 233 | } while(0) 234 | 235 | /** 236 | * Exit the protothread. 237 | * 238 | * This macro causes the protothread to exit. If the protothread was 239 | * spawned by another protothread, the parent protothread will become 240 | * unblocked and can continue to run. 241 | * 242 | * \param pt A pointer to the protothread control structure. 243 | * 244 | * \hideinitializer 245 | */ 246 | #define PT_EXIT(pt) \ 247 | do { \ 248 | PT_INIT(pt); \ 249 | return PT_EXITED; \ 250 | } while(0) 251 | 252 | /** @} */ 253 | 254 | /** 255 | * \name Calling a protothread 256 | * @{ 257 | */ 258 | 259 | /** 260 | * Schedule a protothread. 261 | * 262 | * This function shedules a protothread. The return value of the 263 | * function is non-zero if the protothread is running or zero if the 264 | * protothread has exited. 265 | * 266 | * \param f The call to the C function implementing the protothread to 267 | * be scheduled 268 | * 269 | * \hideinitializer 270 | */ 271 | #define PT_SCHEDULE(f) ((f) == PT_WAITING) 272 | 273 | /** @} */ 274 | 275 | /** 276 | * \name Yielding from a protothread 277 | * @{ 278 | */ 279 | 280 | /** 281 | * Yield from the current protothread. 282 | * 283 | * This function will yield the protothread, thereby allowing other 284 | * processing to take place in the system. 285 | * 286 | * \param pt A pointer to the protothread control structure. 287 | * 288 | * \hideinitializer 289 | */ 290 | #define PT_YIELD(pt) \ 291 | do { \ 292 | PT_YIELD_FLAG = 0; \ 293 | LC_SET((pt)->lc); \ 294 | if(PT_YIELD_FLAG == 0) { \ 295 | return PT_YIELDED; \ 296 | } \ 297 | } while(0) 298 | 299 | /** 300 | * \brief Yield from the protothread until a condition occurs. 301 | * \param pt A pointer to the protothread control structure. 302 | * \param cond The condition. 303 | * 304 | * This function will yield the protothread, until the 305 | * specified condition evaluates to true. 306 | * 307 | * 308 | * \hideinitializer 309 | */ 310 | #define PT_YIELD_UNTIL(pt, cond) \ 311 | do { \ 312 | PT_YIELD_FLAG = 0; \ 313 | LC_SET((pt)->lc); \ 314 | if((PT_YIELD_FLAG == 0) || !(cond)) { \ 315 | return PT_YIELDED; \ 316 | } \ 317 | } while(0) 318 | 319 | /** @} */ 320 | 321 | #endif /* __PT_H__ */ 322 | 323 | /** @} */ 324 | -------------------------------------------------------------------------------- /src/uip/psock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: psock.c,v 1.2 2006/06/12 08:00:30 adam Exp $ 34 | */ 35 | 36 | #include 37 | #include 38 | 39 | #include "uipopt.h" 40 | #include "psock.h" 41 | #include "uip.h" 42 | 43 | #define STATE_NONE 0 44 | #define STATE_ACKED 1 45 | #define STATE_READ 2 46 | #define STATE_BLOCKED_NEWDATA 3 47 | #define STATE_BLOCKED_CLOSE 4 48 | #define STATE_BLOCKED_SEND 5 49 | #define STATE_DATA_SENT 6 50 | 51 | /* 52 | * Return value of the buffering functions that indicates that a 53 | * buffer was not filled by incoming data. 54 | * 55 | */ 56 | #define BUF_NOT_FULL 0 57 | #define BUF_NOT_FOUND 0 58 | 59 | /* 60 | * Return value of the buffering functions that indicates that a 61 | * buffer was completely filled by incoming data. 62 | * 63 | */ 64 | #define BUF_FULL 1 65 | 66 | /* 67 | * Return value of the buffering functions that indicates that an 68 | * end-marker byte was found. 69 | * 70 | */ 71 | #define BUF_FOUND 2 72 | 73 | /*---------------------------------------------------------------------------*/ 74 | static void 75 | buf_setup(struct psock_buf *buf, 76 | u8_t *bufptr, u16_t bufsize) 77 | { 78 | buf->ptr = bufptr; 79 | buf->left = bufsize; 80 | } 81 | /*---------------------------------------------------------------------------*/ 82 | static u8_t 83 | buf_bufdata(struct psock_buf *buf, u16_t len, 84 | u8_t **dataptr, u16_t *datalen) 85 | { 86 | if(*datalen < buf->left) { 87 | memcpy(buf->ptr, *dataptr, *datalen); 88 | buf->ptr += *datalen; 89 | buf->left -= *datalen; 90 | *dataptr += *datalen; 91 | *datalen = 0; 92 | return BUF_NOT_FULL; 93 | } else if(*datalen == buf->left) { 94 | memcpy(buf->ptr, *dataptr, *datalen); 95 | buf->ptr += *datalen; 96 | buf->left = 0; 97 | *dataptr += *datalen; 98 | *datalen = 0; 99 | return BUF_FULL; 100 | } else { 101 | memcpy(buf->ptr, *dataptr, buf->left); 102 | buf->ptr += buf->left; 103 | *datalen -= buf->left; 104 | *dataptr += buf->left; 105 | buf->left = 0; 106 | return BUF_FULL; 107 | } 108 | } 109 | /*---------------------------------------------------------------------------*/ 110 | static u8_t 111 | buf_bufto(register struct psock_buf *buf, u8_t endmarker, 112 | register u8_t **dataptr, register u16_t *datalen) 113 | { 114 | u8_t c; 115 | while(buf->left > 0 && *datalen > 0) { 116 | c = *buf->ptr = **dataptr; 117 | ++*dataptr; 118 | ++buf->ptr; 119 | --*datalen; 120 | --buf->left; 121 | 122 | if(c == endmarker) { 123 | return BUF_FOUND; 124 | } 125 | } 126 | 127 | if(*datalen == 0) { 128 | return BUF_NOT_FOUND; 129 | } 130 | 131 | while(*datalen > 0) { 132 | c = **dataptr; 133 | --*datalen; 134 | ++*dataptr; 135 | 136 | if(c == endmarker) { 137 | return BUF_FOUND | BUF_FULL; 138 | } 139 | } 140 | 141 | return BUF_FULL; 142 | } 143 | /*---------------------------------------------------------------------------*/ 144 | static char 145 | send_data(register struct psock *s) 146 | { 147 | if(s->state != STATE_DATA_SENT || uip_rexmit()) { 148 | if(s->sendlen > uip_mss()) { 149 | uip_send(s->sendptr, uip_mss()); 150 | } else { 151 | uip_send(s->sendptr, s->sendlen); 152 | } 153 | s->state = STATE_DATA_SENT; 154 | return 1; 155 | } 156 | return 0; 157 | } 158 | /*---------------------------------------------------------------------------*/ 159 | static char 160 | data_acked(register struct psock *s) 161 | { 162 | if(s->state == STATE_DATA_SENT && uip_acked()) { 163 | if(s->sendlen > uip_mss()) { 164 | s->sendlen -= uip_mss(); 165 | s->sendptr += uip_mss(); 166 | } else { 167 | s->sendptr += s->sendlen; 168 | s->sendlen = 0; 169 | } 170 | s->state = STATE_ACKED; 171 | return 1; 172 | } 173 | return 0; 174 | } 175 | /*---------------------------------------------------------------------------*/ 176 | PT_THREAD(psock_send(register struct psock *s, const char *buf, 177 | unsigned int len)) 178 | { 179 | PT_BEGIN(&s->psockpt); 180 | 181 | /* If there is no data to send, we exit immediately. */ 182 | if(len == 0) { 183 | PT_EXIT(&s->psockpt); 184 | } 185 | 186 | /* Save the length of and a pointer to the data that is to be 187 | sent. */ 188 | s->sendptr = buf; 189 | s->sendlen = len; 190 | 191 | s->state = STATE_NONE; 192 | 193 | /* We loop here until all data is sent. The s->sendlen variable is 194 | updated by the data_sent() function. */ 195 | while(s->sendlen > 0) { 196 | 197 | /* 198 | * The condition for this PT_WAIT_UNTIL is a little tricky: the 199 | * protothread will wait here until all data has been acknowledged 200 | * (data_acked() returns true) and until all data has been sent 201 | * (send_data() returns true). The two functions data_acked() and 202 | * send_data() must be called in succession to ensure that all 203 | * data is sent. Therefore the & operator is used instead of the 204 | * && operator, which would cause only the data_acked() function 205 | * to be called when it returns false. 206 | */ 207 | PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s)); 208 | } 209 | 210 | s->state = STATE_NONE; 211 | 212 | PT_END(&s->psockpt); 213 | } 214 | /*---------------------------------------------------------------------------*/ 215 | PT_THREAD(psock_generator_send(register struct psock *s, 216 | unsigned short (*generate)(void *), void *arg)) 217 | { 218 | PT_BEGIN(&s->psockpt); 219 | 220 | /* Ensure that there is a generator function to call. */ 221 | if(generate == NULL) { 222 | PT_EXIT(&s->psockpt); 223 | } 224 | 225 | /* Call the generator function to generate the data in the 226 | uip_appdata buffer. */ 227 | s->sendlen = generate(arg); 228 | s->sendptr = uip_appdata; 229 | 230 | s->state = STATE_NONE; 231 | do { 232 | /* Call the generator function again if we are called to perform a 233 | retransmission. */ 234 | if(uip_rexmit()) { 235 | generate(arg); 236 | } 237 | /* Wait until all data is sent and acknowledged. */ 238 | PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s)); 239 | } while(s->sendlen > 0); 240 | 241 | s->state = STATE_NONE; 242 | 243 | PT_END(&s->psockpt); 244 | } 245 | /*---------------------------------------------------------------------------*/ 246 | u16_t 247 | psock_datalen(struct psock *psock) 248 | { 249 | return psock->bufsize - psock->buf.left; 250 | } 251 | /*---------------------------------------------------------------------------*/ 252 | char 253 | psock_newdata(struct psock *s) 254 | { 255 | if(s->readlen > 0) { 256 | /* There is data in the uip_appdata buffer that has not yet been 257 | read with the PSOCK_READ functions. */ 258 | return 1; 259 | } else if(s->state == STATE_READ) { 260 | /* All data in uip_appdata buffer already consumed. */ 261 | s->state = STATE_BLOCKED_NEWDATA; 262 | return 0; 263 | } else if(uip_newdata()) { 264 | /* There is new data that has not been consumed. */ 265 | return 1; 266 | } else { 267 | /* There is no new data. */ 268 | return 0; 269 | } 270 | } 271 | /*---------------------------------------------------------------------------*/ 272 | PT_THREAD(psock_readto(register struct psock *psock, unsigned char c)) 273 | { 274 | PT_BEGIN(&psock->psockpt); 275 | 276 | buf_setup(&psock->buf, psock->bufptr, psock->bufsize); 277 | 278 | /* XXX: Should add buf_checkmarker() before do{} loop, if 279 | incoming data has been handled while waiting for a write. */ 280 | 281 | do { 282 | if(psock->readlen == 0) { 283 | PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock)); 284 | psock->state = STATE_READ; 285 | psock->readptr = (u8_t *)uip_appdata; 286 | psock->readlen = uip_datalen(); 287 | } 288 | } while((buf_bufto(&psock->buf, c, 289 | &psock->readptr, 290 | &psock->readlen) & BUF_FOUND) == 0); 291 | 292 | if(psock_datalen(psock) == 0) { 293 | psock->state = STATE_NONE; 294 | PT_RESTART(&psock->psockpt); 295 | } 296 | 297 | //fxip_log("ptend"); 298 | PT_END(&psock->psockpt); 299 | } 300 | /*---------------------------------------------------------------------------*/ 301 | PT_THREAD(psock_readbuf(register struct psock *psock)) 302 | { 303 | PT_BEGIN(&psock->psockpt); 304 | 305 | buf_setup(&psock->buf, psock->bufptr, psock->bufsize); 306 | 307 | /* XXX: Should add buf_checkmarker() before do{} loop, if 308 | incoming data has been handled while waiting for a write. */ 309 | 310 | do { 311 | if(psock->readlen == 0) { 312 | PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock)); 313 | //printf("Waited for newdata\n"); 314 | psock->state = STATE_READ; 315 | psock->readptr = (u8_t *)uip_appdata; 316 | psock->readlen = uip_datalen(); 317 | } 318 | } while(buf_bufdata(&psock->buf, psock->bufsize, 319 | &psock->readptr, 320 | &psock->readlen) != BUF_FULL); 321 | 322 | if(psock_datalen(psock) == 0) { 323 | psock->state = STATE_NONE; 324 | PT_RESTART(&psock->psockpt); 325 | } 326 | PT_END(&psock->psockpt); 327 | } 328 | /*---------------------------------------------------------------------------*/ 329 | void 330 | psock_init(register struct psock *psock, char *buffer, unsigned int buffersize) 331 | { 332 | psock->state = STATE_NONE; 333 | psock->readlen = 0; 334 | psock->bufptr = buffer; 335 | psock->bufsize = buffersize; 336 | buf_setup(&psock->buf, buffer, buffersize); 337 | PT_INIT(&psock->pt); 338 | PT_INIT(&psock->psockpt); 339 | } 340 | /*---------------------------------------------------------------------------*/ 341 | -------------------------------------------------------------------------------- /src/uip/psock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: psock.h,v 1.3 2006/06/12 08:00:30 adam Exp $ 34 | */ 35 | 36 | /** 37 | * \defgroup psock Protosockets library 38 | * @{ 39 | * 40 | * The protosocket library provides an interface to the uIP stack that is 41 | * similar to the traditional BSD socket interface. Unlike programs 42 | * written for the ordinary uIP event-driven interface, programs 43 | * written with the protosocket library are executed in a sequential 44 | * fashion and does not have to be implemented as explicit state 45 | * machines. 46 | * 47 | * Protosockets only work with TCP connections. 48 | * 49 | * The protosocket library uses \ref pt protothreads to provide 50 | * sequential control flow. This makes the protosockets lightweight in 51 | * terms of memory, but also means that protosockets inherits the 52 | * functional limitations of protothreads. Each protosocket lives only 53 | * within a single function. Automatic variables (stack variables) are 54 | * not retained across a protosocket library function call. 55 | * 56 | * \note Because the protosocket library uses protothreads, local 57 | * variables will not always be saved across a call to a protosocket 58 | * library function. It is therefore advised that local variables are 59 | * used with extreme care. 60 | * 61 | * The protosocket library provides functions for sending data without 62 | * having to deal with retransmissions and acknowledgements, as well 63 | * as functions for reading data without having to deal with data 64 | * being split across more than one TCP segment. 65 | * 66 | * Because each protosocket runs as a protothread, the protosocket has to be 67 | * started with a call to PSOCK_BEGIN() at the start of the function 68 | * in which the protosocket is used. Similarly, the protosocket protothread can 69 | * be terminated by a call to PSOCK_EXIT(). 70 | * 71 | */ 72 | 73 | /** 74 | * \file 75 | * Protosocket library header file 76 | * \author 77 | * Adam Dunkels 78 | * 79 | */ 80 | 81 | #ifndef __PSOCK_H__ 82 | #define __PSOCK_H__ 83 | 84 | #include "uipopt.h" 85 | #include "pt.h" 86 | 87 | /* 88 | * The structure that holds the state of a buffer. 89 | * 90 | * This structure holds the state of a uIP buffer. The structure has 91 | * no user-visible elements, but is used through the functions 92 | * provided by the library. 93 | * 94 | */ 95 | struct psock_buf { 96 | u8_t *ptr; 97 | unsigned short left; 98 | }; 99 | 100 | /** 101 | * The representation of a protosocket. 102 | * 103 | * The protosocket structrure is an opaque structure with no user-visible 104 | * elements. 105 | */ 106 | struct psock { 107 | struct pt pt, psockpt; /* Protothreads - one that's using the psock 108 | functions, and one that runs inside the 109 | psock functions. */ 110 | const u8_t *sendptr; /* Pointer to the next data to be sent. */ 111 | u8_t *readptr; /* Pointer to the next data to be read. */ 112 | 113 | char *bufptr; /* Pointer to the buffer used for buffering 114 | incoming data. */ 115 | 116 | u16_t sendlen; /* The number of bytes left to be sent. */ 117 | u16_t readlen; /* The number of bytes left to be read. */ 118 | 119 | struct psock_buf buf; /* The structure holding the state of the 120 | input buffer. */ 121 | unsigned int bufsize; /* The size of the input buffer. */ 122 | 123 | unsigned char state; /* The state of the protosocket. */ 124 | }; 125 | 126 | void psock_init(struct psock *psock, char *buffer, unsigned int buffersize); 127 | /** 128 | * Initialize a protosocket. 129 | * 130 | * This macro initializes a protosocket and must be called before the 131 | * protosocket is used. The initialization also specifies the input buffer 132 | * for the protosocket. 133 | * 134 | * \param psock (struct psock *) A pointer to the protosocket to be 135 | * initialized 136 | * 137 | * \param buffer (char *) A pointer to the input buffer for the 138 | * protosocket. 139 | * 140 | * \param buffersize (unsigned int) The size of the input buffer. 141 | * 142 | * \hideinitializer 143 | */ 144 | #define PSOCK_INIT(psock, buffer, buffersize) \ 145 | psock_init(psock, buffer, buffersize) 146 | 147 | /** 148 | * Start the protosocket protothread in a function. 149 | * 150 | * This macro starts the protothread associated with the protosocket and 151 | * must come before other protosocket calls in the function it is used. 152 | * 153 | * \param psock (struct psock *) A pointer to the protosocket to be 154 | * started. 155 | * 156 | * \hideinitializer 157 | */ 158 | #define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt)) 159 | 160 | PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len)); 161 | /** 162 | * Send data. 163 | * 164 | * This macro sends data over a protosocket. The protosocket protothread blocks 165 | * until all data has been sent and is known to have been received by 166 | * the remote end of the TCP connection. 167 | * 168 | * \param psock (struct psock *) A pointer to the protosocket over which 169 | * data is to be sent. 170 | * 171 | * \param data (char *) A pointer to the data that is to be sent. 172 | * 173 | * \param datalen (unsigned int) The length of the data that is to be 174 | * sent. 175 | * 176 | * \hideinitializer 177 | */ 178 | #define PSOCK_SEND(psock, data, datalen) \ 179 | PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen)) 180 | 181 | /** 182 | * \brief Send a null-terminated string. 183 | * \param psock Pointer to the protosocket. 184 | * \param str The string to be sent. 185 | * 186 | * This function sends a null-terminated string over the 187 | * protosocket. 188 | * 189 | * \hideinitializer 190 | */ 191 | #define PSOCK_SEND_STR(psock, str) \ 192 | PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str))) 193 | 194 | PT_THREAD(psock_generator_send(struct psock *psock, 195 | unsigned short (*f)(void *), void *arg)); 196 | 197 | /** 198 | * \brief Generate data with a function and send it 199 | * \param psock Pointer to the protosocket. 200 | * \param generator Pointer to the generator function 201 | * \param arg Argument to the generator function 202 | * 203 | * This function generates data and sends it over the 204 | * protosocket. This can be used to dynamically generate 205 | * data for a transmission, instead of generating the data 206 | * in a buffer beforehand. This function reduces the need for 207 | * buffer memory. The generator function is implemented by 208 | * the application, and a pointer to the function is given 209 | * as an argument with the call to PSOCK_GENERATOR_SEND(). 210 | * 211 | * The generator function should place the generated data 212 | * directly in the uip_appdata buffer, and return the 213 | * length of the generated data. The generator function is 214 | * called by the protosocket layer when the data first is 215 | * sent, and once for every retransmission that is needed. 216 | * 217 | * \hideinitializer 218 | */ 219 | #define PSOCK_GENERATOR_SEND(psock, generator, arg) \ 220 | PT_WAIT_THREAD(&((psock)->pt), \ 221 | psock_generator_send(psock, generator, arg)) 222 | 223 | 224 | /** 225 | * Close a protosocket. 226 | * 227 | * This macro closes a protosocket and can only be called from within the 228 | * protothread in which the protosocket lives. 229 | * 230 | * \param psock (struct psock *) A pointer to the protosocket that is to 231 | * be closed. 232 | * 233 | * \hideinitializer 234 | */ 235 | #define PSOCK_CLOSE(psock) uip_close() 236 | 237 | PT_THREAD(psock_readbuf(struct psock *psock)); 238 | /** 239 | * Read data until the buffer is full. 240 | * 241 | * This macro will block waiting for data and read the data into the 242 | * input buffer specified with the call to PSOCK_INIT(). Data is read 243 | * until the buffer is full.. 244 | * 245 | * \param psock (struct psock *) A pointer to the protosocket from which 246 | * data should be read. 247 | * 248 | * \hideinitializer 249 | */ 250 | #define PSOCK_READBUF(psock) \ 251 | PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock)) 252 | 253 | PT_THREAD(psock_readto(struct psock *psock, unsigned char c)); 254 | /** 255 | * Read data up to a specified character. 256 | * 257 | * This macro will block waiting for data and read the data into the 258 | * input buffer specified with the call to PSOCK_INIT(). Data is only 259 | * read until the specifieed character appears in the data stream. 260 | * 261 | * \param psock (struct psock *) A pointer to the protosocket from which 262 | * data should be read. 263 | * 264 | * \param c (char) The character at which to stop reading. 265 | * 266 | * \hideinitializer 267 | */ 268 | #define PSOCK_READTO(psock, c) \ 269 | PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c)) 270 | 271 | /** 272 | * The length of the data that was previously read. 273 | * 274 | * This macro returns the length of the data that was previously read 275 | * using PSOCK_READTO() or PSOCK_READ(). 276 | * 277 | * \param psock (struct psock *) A pointer to the protosocket holding the data. 278 | * 279 | * \hideinitializer 280 | */ 281 | #define PSOCK_DATALEN(psock) psock_datalen(psock) 282 | 283 | u16_t psock_datalen(struct psock *psock); 284 | 285 | /** 286 | * Exit the protosocket's protothread. 287 | * 288 | * This macro terminates the protothread of the protosocket and should 289 | * almost always be used in conjunction with PSOCK_CLOSE(). 290 | * 291 | * \sa PSOCK_CLOSE_EXIT() 292 | * 293 | * \param psock (struct psock *) A pointer to the protosocket. 294 | * 295 | * \hideinitializer 296 | */ 297 | #define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt)) 298 | 299 | /** 300 | * Close a protosocket and exit the protosocket's protothread. 301 | * 302 | * This macro closes a protosocket and exits the protosocket's protothread. 303 | * 304 | * \param psock (struct psock *) A pointer to the protosocket. 305 | * 306 | * \hideinitializer 307 | */ 308 | #define PSOCK_CLOSE_EXIT(psock) \ 309 | do { \ 310 | PSOCK_CLOSE(psock); \ 311 | PSOCK_EXIT(psock); \ 312 | } while(0) 313 | 314 | /** 315 | * Declare the end of a protosocket's protothread. 316 | * 317 | * This macro is used for declaring that the protosocket's protothread 318 | * ends. It must always be used together with a matching PSOCK_BEGIN() 319 | * macro. 320 | * 321 | * \param psock (struct psock *) A pointer to the protosocket. 322 | * 323 | * \hideinitializer 324 | */ 325 | #define PSOCK_END(psock) PT_END(&((psock)->pt)) 326 | 327 | char psock_newdata(struct psock *s); 328 | 329 | /** 330 | * Check if new data has arrived on a protosocket. 331 | * 332 | * This macro is used in conjunction with the PSOCK_WAIT_UNTIL() 333 | * macro to check if data has arrived on a protosocket. 334 | * 335 | * \param psock (struct psock *) A pointer to the protosocket. 336 | * 337 | * \hideinitializer 338 | */ 339 | #define PSOCK_NEWDATA(psock) psock_newdata(psock) 340 | 341 | /** 342 | * Wait until a condition is true. 343 | * 344 | * This macro blocks the protothread until the specified condition is 345 | * true. The macro PSOCK_NEWDATA() can be used to check if new data 346 | * arrives when the protosocket is waiting. 347 | * 348 | * Typically, this macro is used as follows: 349 | * 350 | \code 351 | PT_THREAD(thread(struct psock *s, struct timer *t)) 352 | { 353 | PSOCK_BEGIN(s); 354 | 355 | PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t)); 356 | 357 | if(PSOCK_NEWDATA(s)) { 358 | PSOCK_READTO(s, '\n'); 359 | } else { 360 | handle_timed_out(s); 361 | } 362 | 363 | PSOCK_END(s); 364 | } 365 | \endcode 366 | * 367 | * \param psock (struct psock *) A pointer to the protosocket. 368 | * \param condition The condition to wait for. 369 | * 370 | * \hideinitializer 371 | */ 372 | #define PSOCK_WAIT_UNTIL(psock, condition) \ 373 | PT_WAIT_UNTIL(&((psock)->pt), (condition)); 374 | 375 | #define PSOCK_WAIT_THREAD(psock, condition) \ 376 | PT_WAIT_THREAD(&((psock)->pt), (condition)) 377 | 378 | #endif /* __PSOCK_H__ */ 379 | 380 | /** @} */ 381 | -------------------------------------------------------------------------------- /src/uip/uip_arp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup uip 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \defgroup uiparp uIP Address Resolution Protocol 8 | * @{ 9 | * 10 | * The Address Resolution Protocol ARP is used for mapping between IP 11 | * addresses and link level addresses such as the Ethernet MAC 12 | * addresses. ARP uses broadcast queries to ask for the link level 13 | * address of a known IP address and the host which is configured with 14 | * the IP address for which the query was meant, will respond with its 15 | * link level address. 16 | * 17 | * \note This ARP implementation only supports Ethernet. 18 | */ 19 | 20 | /** 21 | * \file 22 | * Implementation of the ARP Address Resolution Protocol. 23 | * \author Adam Dunkels 24 | * 25 | */ 26 | 27 | /* 28 | * Copyright (c) 2001-2003, Adam Dunkels. 29 | * All rights reserved. 30 | * 31 | * Redistribution and use in source and binary forms, with or without 32 | * modification, are permitted provided that the following conditions 33 | * are met: 34 | * 1. Redistributions of source code must retain the above copyright 35 | * notice, this list of conditions and the following disclaimer. 36 | * 2. Redistributions in binary form must reproduce the above copyright 37 | * notice, this list of conditions and the following disclaimer in the 38 | * documentation and/or other materials provided with the distribution. 39 | * 3. The name of the author may not be used to endorse or promote 40 | * products derived from this software without specific prior 41 | * written permission. 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 44 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 45 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 47 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 49 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 51 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 52 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 53 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 | * 55 | * This file is part of the uIP TCP/IP stack. 56 | * 57 | * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $ 58 | * 59 | */ 60 | 61 | 62 | #include "uip_arp.h" 63 | 64 | #include 65 | 66 | struct arp_hdr { 67 | struct uip_eth_hdr ethhdr; 68 | u16_t hwtype; 69 | u16_t protocol; 70 | u8_t hwlen; 71 | u8_t protolen; 72 | u16_t opcode; 73 | struct uip_eth_addr shwaddr; 74 | u16_t sipaddr[2]; 75 | struct uip_eth_addr dhwaddr; 76 | u16_t dipaddr[2]; 77 | }; 78 | 79 | struct ethip_hdr { 80 | struct uip_eth_hdr ethhdr; 81 | /* IP header. */ 82 | u8_t vhl, 83 | tos, 84 | len[2], 85 | ipid[2], 86 | ipoffset[2], 87 | ttl, 88 | proto; 89 | u16_t ipchksum; 90 | u16_t srcipaddr[2], 91 | destipaddr[2]; 92 | }; 93 | 94 | #define ARP_REQUEST 1 95 | #define ARP_REPLY 2 96 | 97 | #define ARP_HWTYPE_ETH 1 98 | 99 | struct arp_entry { 100 | u16_t ipaddr[2]; 101 | struct uip_eth_addr ethaddr; 102 | u8_t time; 103 | }; 104 | 105 | static const struct uip_eth_addr broadcast_ethaddr = 106 | {{0xff,0xff,0xff,0xff,0xff,0xff}}; 107 | static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff}; 108 | 109 | static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; 110 | static u16_t ipaddr[2]; 111 | static u8_t i, c; 112 | 113 | static u8_t arptime; 114 | static u8_t tmpage; 115 | 116 | #define BUF ((struct arp_hdr *)&uip_buf[0]) 117 | #define IPBUF ((struct ethip_hdr *)&uip_buf[0]) 118 | /*-----------------------------------------------------------------------------------*/ 119 | /** 120 | * Initialize the ARP module. 121 | * 122 | */ 123 | /*-----------------------------------------------------------------------------------*/ 124 | void 125 | uip_arp_init(void) 126 | { 127 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 128 | memset(arp_table[i].ipaddr, 0, 4); 129 | } 130 | } 131 | /*-----------------------------------------------------------------------------------*/ 132 | /** 133 | * Periodic ARP processing function. 134 | * 135 | * This function performs periodic timer processing in the ARP module 136 | * and should be called at regular intervals. The recommended interval 137 | * is 10 seconds between the calls. 138 | * 139 | */ 140 | /*-----------------------------------------------------------------------------------*/ 141 | void 142 | uip_arp_timer(void) 143 | { 144 | struct arp_entry *tabptr; 145 | 146 | ++arptime; 147 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 148 | tabptr = &arp_table[i]; 149 | if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && 150 | arptime - tabptr->time >= UIP_ARP_MAXAGE) { 151 | memset(tabptr->ipaddr, 0, 4); 152 | } 153 | } 154 | 155 | } 156 | /*-----------------------------------------------------------------------------------*/ 157 | static void 158 | uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) 159 | { 160 | register struct arp_entry *tabptr; 161 | /* Walk through the ARP mapping table and try to find an entry to 162 | update. If none is found, the IP -> MAC address mapping is 163 | inserted in the ARP table. */ 164 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 165 | 166 | tabptr = &arp_table[i]; 167 | /* Only check those entries that are actually in use. */ 168 | if(tabptr->ipaddr[0] != 0 && 169 | tabptr->ipaddr[1] != 0) { 170 | 171 | /* Check if the source IP address of the incoming packet matches 172 | the IP address in this ARP table entry. */ 173 | if(ipaddr[0] == tabptr->ipaddr[0] && 174 | ipaddr[1] == tabptr->ipaddr[1]) { 175 | 176 | /* An old entry found, update this and return. */ 177 | memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); 178 | tabptr->time = arptime; 179 | 180 | return; 181 | } 182 | } 183 | } 184 | 185 | /* If we get here, no existing ARP table entry was found, so we 186 | create one. */ 187 | 188 | /* First, we try to find an unused entry in the ARP table. */ 189 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 190 | tabptr = &arp_table[i]; 191 | if(tabptr->ipaddr[0] == 0 && 192 | tabptr->ipaddr[1] == 0) { 193 | break; 194 | } 195 | } 196 | 197 | /* If no unused entry is found, we try to find the oldest entry and 198 | throw it away. */ 199 | if(i == UIP_ARPTAB_SIZE) { 200 | tmpage = 0; 201 | c = 0; 202 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 203 | tabptr = &arp_table[i]; 204 | if(arptime - tabptr->time > tmpage) { 205 | tmpage = arptime - tabptr->time; 206 | c = i; 207 | } 208 | } 209 | i = c; 210 | tabptr = &arp_table[i]; 211 | } 212 | 213 | /* Now, i is the ARP table entry which we will fill with the new 214 | information. */ 215 | memcpy(tabptr->ipaddr, ipaddr, 4); 216 | memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); 217 | tabptr->time = arptime; 218 | } 219 | /*-----------------------------------------------------------------------------------*/ 220 | /** 221 | * ARP processing for incoming IP packets 222 | * 223 | * This function should be called by the device driver when an IP 224 | * packet has been received. The function will check if the address is 225 | * in the ARP cache, and if so the ARP cache entry will be 226 | * refreshed. If no ARP cache entry was found, a new one is created. 227 | * 228 | * This function expects an IP packet with a prepended Ethernet header 229 | * in the uip_buf[] buffer, and the length of the packet in the global 230 | * variable uip_len. 231 | */ 232 | /*-----------------------------------------------------------------------------------*/ 233 | #if 0 234 | void 235 | uip_arp_ipin(void) 236 | { 237 | uip_len -= sizeof(struct uip_eth_hdr); 238 | 239 | /* Only insert/update an entry if the source IP address of the 240 | incoming IP packet comes from a host on the local network. */ 241 | if((IPBUF->srcipaddr[0] & uip_netmask[0]) != 242 | (uip_hostaddr[0] & uip_netmask[0])) { 243 | return; 244 | } 245 | if((IPBUF->srcipaddr[1] & uip_netmask[1]) != 246 | (uip_hostaddr[1] & uip_netmask[1])) { 247 | return; 248 | } 249 | uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); 250 | 251 | return; 252 | } 253 | #endif /* 0 */ 254 | /*-----------------------------------------------------------------------------------*/ 255 | /** 256 | * ARP processing for incoming ARP packets. 257 | * 258 | * This function should be called by the device driver when an ARP 259 | * packet has been received. The function will act differently 260 | * depending on the ARP packet type: if it is a reply for a request 261 | * that we previously sent out, the ARP cache will be filled in with 262 | * the values from the ARP reply. If the incoming ARP packet is an ARP 263 | * request for our IP address, an ARP reply packet is created and put 264 | * into the uip_buf[] buffer. 265 | * 266 | * When the function returns, the value of the global variable uip_len 267 | * indicates whether the device driver should send out a packet or 268 | * not. If uip_len is zero, no packet should be sent. If uip_len is 269 | * non-zero, it contains the length of the outbound packet that is 270 | * present in the uip_buf[] buffer. 271 | * 272 | * This function expects an ARP packet with a prepended Ethernet 273 | * header in the uip_buf[] buffer, and the length of the packet in the 274 | * global variable uip_len. 275 | */ 276 | /*-----------------------------------------------------------------------------------*/ 277 | void 278 | uip_arp_arpin(void) 279 | { 280 | 281 | if(uip_len < sizeof(struct arp_hdr)) { 282 | uip_len = 0; 283 | return; 284 | } 285 | uip_len = 0; 286 | 287 | switch(BUF->opcode) { 288 | case HTONS(ARP_REQUEST): 289 | /* ARP request. If it asked for our address, we send out a 290 | reply. */ 291 | if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { 292 | /* First, we register the one who made the request in our ARP 293 | table, since it is likely that we will do more communication 294 | with this host in the future. */ 295 | uip_arp_update(BUF->sipaddr, &BUF->shwaddr); 296 | 297 | /* The reply opcode is 2. */ 298 | BUF->opcode = HTONS(2); 299 | 300 | memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); 301 | memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); 302 | memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 303 | memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); 304 | 305 | BUF->dipaddr[0] = BUF->sipaddr[0]; 306 | BUF->dipaddr[1] = BUF->sipaddr[1]; 307 | BUF->sipaddr[0] = uip_hostaddr[0]; 308 | BUF->sipaddr[1] = uip_hostaddr[1]; 309 | 310 | BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); 311 | uip_len = sizeof(struct arp_hdr); 312 | } 313 | break; 314 | case HTONS(ARP_REPLY): 315 | /* ARP reply. We insert or update the ARP table if it was meant 316 | for us. */ 317 | if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { 318 | uip_arp_update(BUF->sipaddr, &BUF->shwaddr); 319 | } 320 | break; 321 | } 322 | 323 | return; 324 | } 325 | /*-----------------------------------------------------------------------------------*/ 326 | /** 327 | * Prepend Ethernet header to an outbound IP packet and see if we need 328 | * to send out an ARP request. 329 | * 330 | * This function should be called before sending out an IP packet. The 331 | * function checks the destination IP address of the IP packet to see 332 | * what Ethernet MAC address that should be used as a destination MAC 333 | * address on the Ethernet. 334 | * 335 | * If the destination IP address is in the local network (determined 336 | * by logical ANDing of netmask and our IP address), the function 337 | * checks the ARP cache to see if an entry for the destination IP 338 | * address is found. If so, an Ethernet header is prepended and the 339 | * function returns. If no ARP cache entry is found for the 340 | * destination IP address, the packet in the uip_buf[] is replaced by 341 | * an ARP request packet for the IP address. The IP packet is dropped 342 | * and it is assumed that they higher level protocols (e.g., TCP) 343 | * eventually will retransmit the dropped packet. 344 | * 345 | * If the destination IP address is not on the local network, the IP 346 | * address of the default router is used instead. 347 | * 348 | * When the function returns, a packet is present in the uip_buf[] 349 | * buffer, and the length of the packet is in the global variable 350 | * uip_len. 351 | */ 352 | /*-----------------------------------------------------------------------------------*/ 353 | void 354 | uip_arp_out(void) 355 | { 356 | struct arp_entry *tabptr; 357 | 358 | /* Find the destination IP address in the ARP table and construct 359 | the Ethernet header. If the destination IP addres isn't on the 360 | local network, we use the default router's IP address instead. 361 | 362 | If not ARP table entry is found, we overwrite the original IP 363 | packet with an ARP request for the IP address. */ 364 | 365 | /* First check if destination is a local broadcast. */ 366 | if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) { 367 | memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); 368 | } else { 369 | /* Check if the destination address is on the local network. */ 370 | if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { 371 | /* Destination address was not on the local network, so we need to 372 | use the default router's IP address instead of the destination 373 | address when determining the MAC address. */ 374 | uip_ipaddr_copy(ipaddr, uip_draddr); 375 | } else { 376 | /* Else, we use the destination IP address. */ 377 | uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); 378 | } 379 | 380 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 381 | tabptr = &arp_table[i]; 382 | if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { 383 | break; 384 | } 385 | } 386 | 387 | if(i == UIP_ARPTAB_SIZE) { 388 | /* The destination address was not in our ARP table, so we 389 | overwrite the IP packet with an ARP request. */ 390 | 391 | memset(BUF->ethhdr.dest.addr, 0xff, 6); 392 | memset(BUF->dhwaddr.addr, 0x00, 6); 393 | memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 394 | memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); 395 | 396 | uip_ipaddr_copy(BUF->dipaddr, ipaddr); 397 | uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); 398 | BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ 399 | BUF->hwtype = HTONS(ARP_HWTYPE_ETH); 400 | BUF->protocol = HTONS(UIP_ETHTYPE_IP); 401 | BUF->hwlen = 6; 402 | BUF->protolen = 4; 403 | BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); 404 | 405 | uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; 406 | 407 | uip_len = sizeof(struct arp_hdr); 408 | return; 409 | } 410 | 411 | /* Build an ethernet header. */ 412 | memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); 413 | } 414 | memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 415 | 416 | IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); 417 | 418 | uip_len += sizeof(struct uip_eth_hdr); 419 | } 420 | /*-----------------------------------------------------------------------------------*/ 421 | 422 | /** @} */ 423 | /** @} */ 424 | -------------------------------------------------------------------------------- /src/uip/uip-fw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the uIP TCP/IP stack 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | * $Id: uip-fw.c,v 1.2 2006/06/12 08:00:30 adam Exp $ 34 | */ 35 | /** 36 | * \addtogroup uip 37 | * @{ 38 | */ 39 | 40 | /** 41 | * \defgroup uipfw uIP packet forwarding 42 | * @{ 43 | * 44 | */ 45 | 46 | /** 47 | * \file 48 | * uIP packet forwarding. 49 | * \author Adam Dunkels 50 | * 51 | * This file implements a number of simple functions which do packet 52 | * forwarding over multiple network interfaces with uIP. 53 | * 54 | */ 55 | 56 | #include "uip.h" 57 | #include "uip_arch.h" 58 | #include "uip-fw.h" 59 | 60 | #include /* for memcpy() */ 61 | 62 | /* 63 | * The list of registered network interfaces. 64 | */ 65 | static struct uip_fw_netif *netifs = NULL; 66 | 67 | /* 68 | * A pointer to the default network interface. 69 | */ 70 | static struct uip_fw_netif *defaultnetif = NULL; 71 | 72 | struct tcpip_hdr { 73 | /* IP header. */ 74 | u8_t vhl, 75 | tos; 76 | u16_t len, 77 | ipid, 78 | ipoffset; 79 | u8_t ttl, 80 | proto; 81 | u16_t ipchksum; 82 | u16_t srcipaddr[2], 83 | destipaddr[2]; 84 | 85 | /* TCP header. */ 86 | u16_t srcport, 87 | destport; 88 | u8_t seqno[4], 89 | ackno[4], 90 | tcpoffset, 91 | flags, 92 | wnd[2]; 93 | u16_t tcpchksum; 94 | u8_t urgp[2]; 95 | u8_t optdata[4]; 96 | }; 97 | 98 | struct icmpip_hdr { 99 | /* IP header. */ 100 | u8_t vhl, 101 | tos, 102 | len[2], 103 | ipid[2], 104 | ipoffset[2], 105 | ttl, 106 | proto; 107 | u16_t ipchksum; 108 | u16_t srcipaddr[2], 109 | destipaddr[2]; 110 | /* ICMP (echo) header. */ 111 | u8_t type, icode; 112 | u16_t icmpchksum; 113 | u16_t id, seqno; 114 | u8_t payload[1]; 115 | }; 116 | 117 | /* ICMP ECHO. */ 118 | #define ICMP_ECHO 8 119 | 120 | /* ICMP TIME-EXCEEDED. */ 121 | #define ICMP_TE 11 122 | 123 | /* 124 | * Pointer to the TCP/IP headers of the packet in the uip_buf buffer. 125 | */ 126 | #define BUF ((struct tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) 127 | 128 | /* 129 | * Pointer to the ICMP/IP headers of the packet in the uip_buf buffer. 130 | */ 131 | #define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) 132 | 133 | /* 134 | * Certain fields of an IP packet that are used for identifying 135 | * duplicate packets. 136 | */ 137 | struct fwcache_entry { 138 | u16_t timer; 139 | 140 | u16_t srcipaddr[2]; 141 | u16_t destipaddr[2]; 142 | u16_t ipid; 143 | u8_t proto; 144 | u8_t unused; 145 | 146 | #if notdef 147 | u16_t payload[2]; 148 | #endif 149 | 150 | #if UIP_REASSEMBLY > 0 151 | u16_t len, offset; 152 | #endif 153 | }; 154 | 155 | /* 156 | * The number of packets to remember when looking for duplicates. 157 | */ 158 | #ifdef UIP_CONF_FWCACHE_SIZE 159 | #define FWCACHE_SIZE UIP_CONF_FWCACHE_SIZE 160 | #else 161 | #define FWCACHE_SIZE 2 162 | #endif 163 | 164 | 165 | /* 166 | * A cache of packet header fields which are used for 167 | * identifying duplicate packets. 168 | */ 169 | static struct fwcache_entry fwcache[FWCACHE_SIZE]; 170 | 171 | /** 172 | * \internal 173 | * The time that a packet cache is active. 174 | */ 175 | #define FW_TIME 20 176 | 177 | /*------------------------------------------------------------------------------*/ 178 | /** 179 | * Initialize the uIP packet forwarding module. 180 | */ 181 | /*------------------------------------------------------------------------------*/ 182 | void 183 | uip_fw_init(void) 184 | { 185 | struct uip_fw_netif *t; 186 | defaultnetif = NULL; 187 | while(netifs != NULL) { 188 | t = netifs; 189 | netifs = netifs->next; 190 | t->next = NULL; 191 | } 192 | } 193 | /*------------------------------------------------------------------------------*/ 194 | /** 195 | * \internal 196 | * Check if an IP address is within the network defined by an IP 197 | * address and a netmask. 198 | * 199 | * \param ipaddr The IP address to be checked. 200 | * \param netipaddr The IP address of the network. 201 | * \param netmask The netmask of the network. 202 | * 203 | * \return Non-zero if IP address is in network, zero otherwise. 204 | */ 205 | /*------------------------------------------------------------------------------*/ 206 | static unsigned char 207 | ipaddr_maskcmp(u16_t *ipaddr, u16_t *netipaddr, u16_t *netmask) 208 | { 209 | return (ipaddr[0] & netmask [0]) == (netipaddr[0] & netmask[0]) && 210 | (ipaddr[1] & netmask[1]) == (netipaddr[1] & netmask[1]); 211 | } 212 | /*------------------------------------------------------------------------------*/ 213 | /** 214 | * \internal 215 | * Send out an ICMP TIME-EXCEEDED message. 216 | * 217 | * This function replaces the packet in the uip_buf buffer with the 218 | * ICMP packet. 219 | */ 220 | /*------------------------------------------------------------------------------*/ 221 | static void 222 | time_exceeded(void) 223 | { 224 | u16_t tmp16; 225 | 226 | /* We don't send out ICMP errors for ICMP messages. */ 227 | if(ICMPBUF->proto == UIP_PROTO_ICMP) { 228 | uip_len = 0; 229 | return; 230 | } 231 | /* Copy fields from packet header into payload of this ICMP packet. */ 232 | memcpy(&(ICMPBUF->payload[0]), ICMPBUF, 28); 233 | 234 | /* Set the ICMP type and code. */ 235 | ICMPBUF->type = ICMP_TE; 236 | ICMPBUF->icode = 0; 237 | 238 | /* Calculate the ICMP checksum. */ 239 | ICMPBUF->icmpchksum = 0; 240 | ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36); 241 | 242 | /* Set the IP destination address to be the source address of the 243 | original packet. */ 244 | tmp16= BUF->destipaddr[0]; 245 | BUF->destipaddr[0] = BUF->srcipaddr[0]; 246 | BUF->srcipaddr[0] = tmp16; 247 | tmp16 = BUF->destipaddr[1]; 248 | BUF->destipaddr[1] = BUF->srcipaddr[1]; 249 | BUF->srcipaddr[1] = tmp16; 250 | 251 | /* Set our IP address as the source address. */ 252 | BUF->srcipaddr[0] = uip_hostaddr[0]; 253 | BUF->srcipaddr[1] = uip_hostaddr[1]; 254 | 255 | /* The size of the ICMP time exceeded packet is 36 + the size of the 256 | IP header (20) = 56. */ 257 | uip_len = 56; 258 | ICMPBUF->len[0] = 0; 259 | ICMPBUF->len[1] = uip_len; 260 | 261 | /* Fill in the other fields in the IP header. */ 262 | ICMPBUF->vhl = 0x45; 263 | ICMPBUF->tos = 0; 264 | ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0; 265 | ICMPBUF->ttl = UIP_TTL; 266 | ICMPBUF->proto = UIP_PROTO_ICMP; 267 | 268 | /* Calculate IP checksum. */ 269 | ICMPBUF->ipchksum = 0; 270 | ICMPBUF->ipchksum = ~(uip_ipchksum()); 271 | 272 | 273 | } 274 | /*------------------------------------------------------------------------------*/ 275 | /** 276 | * \internal 277 | * Register a packet in the forwarding cache so that it won't be 278 | * forwarded again. 279 | */ 280 | /*------------------------------------------------------------------------------*/ 281 | static void 282 | fwcache_register(void) 283 | { 284 | struct fwcache_entry *fw; 285 | int i, oldest; 286 | 287 | oldest = FW_TIME; 288 | fw = NULL; 289 | 290 | /* Find the oldest entry in the cache. */ 291 | for(i = 0; i < FWCACHE_SIZE; ++i) { 292 | if(fwcache[i].timer == 0) { 293 | fw = &fwcache[i]; 294 | break; 295 | } else if(fwcache[i].timer <= oldest) { 296 | fw = &fwcache[i]; 297 | oldest = fwcache[i].timer; 298 | } 299 | } 300 | 301 | fw->timer = FW_TIME; 302 | fw->ipid = BUF->ipid; 303 | fw->srcipaddr[0] = BUF->srcipaddr[0]; 304 | fw->srcipaddr[1] = BUF->srcipaddr[1]; 305 | fw->destipaddr[0] = BUF->destipaddr[0]; 306 | fw->destipaddr[1] = BUF->destipaddr[1]; 307 | fw->proto = BUF->proto; 308 | #if notdef 309 | fw->payload[0] = BUF->srcport; 310 | fw->payload[1] = BUF->destport; 311 | #endif 312 | #if UIP_REASSEMBLY > 0 313 | fw->len = BUF->len; 314 | fw->offset = BUF->ipoffset; 315 | #endif 316 | } 317 | /*------------------------------------------------------------------------------*/ 318 | /** 319 | * \internal 320 | * Find a network interface for the IP packet in uip_buf. 321 | */ 322 | /*------------------------------------------------------------------------------*/ 323 | static struct uip_fw_netif * 324 | find_netif(void) 325 | { 326 | struct uip_fw_netif *netif; 327 | 328 | /* Walk through every network interface to check for a match. */ 329 | for(netif = netifs; netif != NULL; netif = netif->next) { 330 | if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr, 331 | netif->netmask)) { 332 | /* If there was a match, we break the loop. */ 333 | return netif; 334 | } 335 | } 336 | 337 | /* If no matching netif was found, we use default netif. */ 338 | return defaultnetif; 339 | } 340 | /*------------------------------------------------------------------------------*/ 341 | /** 342 | * Output an IP packet on the correct network interface. 343 | * 344 | * The IP packet should be present in the uip_buf buffer and its 345 | * length in the global uip_len variable. 346 | * 347 | * \retval UIP_FW_ZEROLEN Indicates that a zero-length packet 348 | * transmission was attempted and that no packet was sent. 349 | * 350 | * \retval UIP_FW_NOROUTE No suitable network interface could be found 351 | * for the outbound packet, and the packet was not sent. 352 | * 353 | * \return The return value from the actual network interface output 354 | * function is passed unmodified as a return value. 355 | */ 356 | /*------------------------------------------------------------------------------*/ 357 | u8_t 358 | uip_fw_output(void) 359 | { 360 | struct uip_fw_netif *netif; 361 | 362 | if(uip_len == 0) { 363 | return UIP_FW_ZEROLEN; 364 | } 365 | 366 | fwcache_register(); 367 | 368 | #if UIP_BROADCAST 369 | /* Link local broadcasts go out on all interfaces. */ 370 | if(/*BUF->proto == UIP_PROTO_UDP &&*/ 371 | BUF->destipaddr[0] == 0xffff && 372 | BUF->destipaddr[1] == 0xffff) { 373 | if(defaultnetif != NULL) { 374 | defaultnetif->output(); 375 | } 376 | for(netif = netifs; netif != NULL; netif = netif->next) { 377 | netif->output(); 378 | } 379 | return UIP_FW_OK; 380 | } 381 | #endif /* UIP_BROADCAST */ 382 | 383 | netif = find_netif(); 384 | /* printf("uip_fw_output: netif %p ->output %p len %d\n", netif, 385 | netif->output, 386 | uip_len);*/ 387 | 388 | if(netif == NULL) { 389 | return UIP_FW_NOROUTE; 390 | } 391 | /* If we now have found a suitable network interface, we call its 392 | output function to send out the packet. */ 393 | return netif->output(); 394 | } 395 | /*------------------------------------------------------------------------------*/ 396 | /** 397 | * Forward an IP packet in the uip_buf buffer. 398 | * 399 | * 400 | * 401 | * \return UIP_FW_FORWARDED if the packet was forwarded, UIP_FW_LOCAL if 402 | * the packet should be processed locally. 403 | */ 404 | /*------------------------------------------------------------------------------*/ 405 | u8_t 406 | uip_fw_forward(void) 407 | { 408 | struct fwcache_entry *fw; 409 | 410 | /* First check if the packet is destined for ourselves and return 0 411 | to indicate that the packet should be processed locally. */ 412 | if(BUF->destipaddr[0] == uip_hostaddr[0] && 413 | BUF->destipaddr[1] == uip_hostaddr[1]) { 414 | return UIP_FW_LOCAL; 415 | } 416 | 417 | /* If we use ping IP address configuration, and our IP address is 418 | not yet configured, we should intercept all ICMP echo packets. */ 419 | #if UIP_PINGADDRCONF 420 | if((uip_hostaddr[0] | uip_hostaddr[1]) == 0 && 421 | BUF->proto == UIP_PROTO_ICMP && 422 | ICMPBUF->type == ICMP_ECHO) { 423 | return UIP_FW_LOCAL; 424 | } 425 | #endif /* UIP_PINGADDRCONF */ 426 | 427 | /* Check if the packet is in the forwarding cache already, and if so 428 | we drop it. */ 429 | 430 | for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) { 431 | if(fw->timer != 0 && 432 | #if UIP_REASSEMBLY > 0 433 | fw->len == BUF->len && 434 | fw->offset == BUF->ipoffset && 435 | #endif 436 | fw->ipid == BUF->ipid && 437 | fw->srcipaddr[0] == BUF->srcipaddr[0] && 438 | fw->srcipaddr[1] == BUF->srcipaddr[1] && 439 | fw->destipaddr[0] == BUF->destipaddr[0] && 440 | fw->destipaddr[1] == BUF->destipaddr[1] && 441 | #if notdef 442 | fw->payload[0] == BUF->srcport && 443 | fw->payload[1] == BUF->destport && 444 | #endif 445 | fw->proto == BUF->proto) { 446 | /* Drop packet. */ 447 | return UIP_FW_FORWARDED; 448 | } 449 | } 450 | 451 | /* If the TTL reaches zero we produce an ICMP time exceeded message 452 | in the uip_buf buffer and forward that packet back to the sender 453 | of the packet. */ 454 | if(BUF->ttl <= 1) { 455 | /* No time exceeded for broadcasts and multicasts! */ 456 | if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) { 457 | return UIP_FW_LOCAL; 458 | } 459 | time_exceeded(); 460 | } 461 | 462 | /* Decrement the TTL (time-to-live) value in the IP header */ 463 | BUF->ttl = BUF->ttl - 1; 464 | 465 | /* Update the IP checksum. */ 466 | if(BUF->ipchksum >= HTONS(0xffff - 0x0100)) { 467 | BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1; 468 | } else { 469 | BUF->ipchksum = BUF->ipchksum + HTONS(0x0100); 470 | } 471 | 472 | if(uip_len > 0) { 473 | uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]; 474 | uip_fw_output(); 475 | } 476 | 477 | #if UIP_BROADCAST 478 | if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) { 479 | return UIP_FW_LOCAL; 480 | } 481 | #endif /* UIP_BROADCAST */ 482 | 483 | /* Return non-zero to indicate that the packet was forwarded and that no 484 | other processing should be made. */ 485 | return UIP_FW_FORWARDED; 486 | } 487 | /*------------------------------------------------------------------------------*/ 488 | /** 489 | * Register a network interface with the forwarding module. 490 | * 491 | * \param netif A pointer to the network interface that is to be 492 | * registered. 493 | */ 494 | /*------------------------------------------------------------------------------*/ 495 | void 496 | uip_fw_register(struct uip_fw_netif *netif) 497 | { 498 | netif->next = netifs; 499 | netifs = netif; 500 | } 501 | /*------------------------------------------------------------------------------*/ 502 | /** 503 | * Register a default network interface. 504 | * 505 | * All packets that don't go out on any of the other interfaces will 506 | * be routed to the default interface. 507 | * 508 | * \param netif A pointer to the network interface that is to be 509 | * registered. 510 | */ 511 | /*------------------------------------------------------------------------------*/ 512 | void 513 | uip_fw_default(struct uip_fw_netif *netif) 514 | { 515 | defaultnetif = netif; 516 | } 517 | /*------------------------------------------------------------------------------*/ 518 | /** 519 | * Perform periodic processing. 520 | */ 521 | /*------------------------------------------------------------------------------*/ 522 | void 523 | uip_fw_periodic(void) 524 | { 525 | struct fwcache_entry *fw; 526 | for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) { 527 | if(fw->timer > 0) { 528 | --fw->timer; 529 | } 530 | } 531 | } 532 | /*------------------------------------------------------------------------------*/ 533 | --------------------------------------------------------------------------------