1212 * @file
1313 * @author Martine Lenders <[email protected] > 1414 * @author Benjamin Valentin <[email protected] > 15+ * @author Bennet Hattesen <[email protected] > 1516 */
1617
1718#include <assert.h>
3132
3233#include "isrpipe.h"
3334#include "mutex.h"
35+ #if IS_USED (MODULE_SLIPDEV_CONFIG )
36+ #include "checksum/crc16_ccitt.h"
37+ #include "net/nanocoap.h"
38+ #endif
3439#include "stdio_uart.h"
3540
41+ #if (IS_USED (MODULE_SLIPDEV_STDIO ) || IS_USED (MODULE_SLIPDEV_CONFIG ))
42+ /* For synchronization with stdio/config threads */
43+ mutex_t slipdev_mutex = MUTEX_INIT ;
44+ #endif
45+
46+ #if IS_USED (MODULE_SLIPDEV_CONFIG )
47+ /* The special init is the result of normal fcs init combined with slipmux config start (0xa9) */
48+ #define SPECIAL_INIT_FCS (0x374cU)
49+ #define COAP_STACKSIZE (1024)
50+
51+ static char coap_stack [COAP_STACKSIZE ];
52+ #endif /* IS_USED(MODULE_SLIPDEV_CONFIG) */
53+
3654static int _check_state (slipdev_t * dev );
3755
3856static inline void slipdev_lock (void )
3957{
40- if (IS_USED (MODULE_SLIPDEV_STDIO )) {
58+ if (IS_USED (MODULE_SLIPDEV_STDIO ) || IS_USED ( MODULE_SLIPDEV_CONFIG ) ) {
4159 mutex_lock (& slipdev_mutex );
4260 }
4361}
4462
4563static inline void slipdev_unlock (void )
4664{
47- if (IS_USED (MODULE_SLIPDEV_STDIO )) {
65+ if (IS_USED (MODULE_SLIPDEV_STDIO ) || IS_USED ( MODULE_SLIPDEV_CONFIG ) ) {
4866 mutex_unlock (& slipdev_mutex );
4967 }
5068}
@@ -54,7 +72,6 @@ static void _slip_rx_cb(void *arg, uint8_t byte)
5472 slipdev_t * dev = arg ;
5573
5674 switch (dev -> state ) {
57- #if IS_USED (MODULE_SLIPDEV_STDIO )
5875 case SLIPDEV_STATE_STDIN :
5976 switch (byte ) {
6077 case SLIPDEV_ESC :
@@ -64,7 +81,11 @@ static void _slip_rx_cb(void *arg, uint8_t byte)
6481 dev -> state = SLIPDEV_STATE_NONE ;
6582 break ;
6683 default :
67- isrpipe_write_one (& stdin_isrpipe , byte );
84+ #if IS_USED (MODULE_SLIPDEV_STDIO )
85+ if (dev -> config .uart == STDIO_UART_DEV ) {
86+ isrpipe_write_one (& stdin_isrpipe , byte );
87+ }
88+ #endif
6889 break ;
6990 }
7091 return ;
@@ -78,24 +99,81 @@ static void _slip_rx_cb(void *arg, uint8_t byte)
7899 break ;
79100 }
80101 dev -> state = SLIPDEV_STATE_STDIN ;
81- isrpipe_write_one (& stdin_isrpipe , byte );
102+ #if IS_USED (MODULE_SLIPDEV_STDIO )
103+ if (dev -> config .uart == STDIO_UART_DEV ) {
104+ isrpipe_write_one (& stdin_isrpipe , byte );
105+ }
106+ #endif
82107 return ;
108+ case SLIPDEV_STATE_CONFIG :
109+ switch (byte ) {
110+ case SLIPDEV_ESC :
111+ dev -> state = SLIPDEV_STATE_CONFIG_ESC ;
112+ break ;
113+ case SLIPDEV_END :
114+ dev -> state = SLIPDEV_STATE_NONE ;
115+ #if IS_USED (MODULE_SLIPDEV_CONFIG )
116+ crb_end_chunk (& dev -> rb_config , true);
117+ thread_flags_set (thread_get (dev -> coap_server_pid ), 1 );
83118#endif
119+ break ;
120+ default :
121+ #if IS_USED (MODULE_SLIPDEV_CONFIG )
122+ /* discard frame if byte can't be added */
123+ if (!crb_add_byte (& dev -> rb_config , byte )) {
124+ DEBUG ("slipdev: rx buffer full, drop frame\n" );
125+ crb_end_chunk (& dev -> rb_config , false);
126+ dev -> state = SLIPDEV_STATE_NONE ;
127+ return ;
128+ }
129+ #endif
130+ break ;
131+ }
132+ return ;
133+ case SLIPDEV_STATE_CONFIG_ESC :
134+ switch (byte ) {
135+ case SLIPDEV_END_ESC :
136+ byte = SLIPDEV_END ;
137+ break ;
138+ case SLIPDEV_ESC_ESC :
139+ byte = SLIPDEV_ESC ;
140+ break ;
141+ }
142+ #if IS_USED (MODULE_SLIPDEV_CONFIG )
143+ /* discard frame if byte can't be added */
144+ if (!crb_add_byte (& dev -> rb_config , byte )) {
145+ DEBUG ("slipdev: rx buffer full, drop frame\n" );
146+ crb_end_chunk (& dev -> rb_config , false);
147+ dev -> state = SLIPDEV_STATE_NONE ;
148+ return ;
149+ }
150+ #endif
151+ dev -> state = SLIPDEV_STATE_CONFIG ;
152+ return ;
84153 case SLIPDEV_STATE_NONE :
85154 /* is diagnostic frame? */
86- if (IS_USED (MODULE_SLIPDEV_STDIO ) &&
87- (byte == SLIPDEV_STDIO_START ) &&
88- (dev -> config .uart == STDIO_UART_DEV )) {
155+ if (byte == SLIPDEV_STDIO_START ) {
89156 dev -> state = SLIPDEV_STATE_STDIN ;
90157 return ;
91158 }
92159
160+ if (byte == SLIPDEV_CONFIG_START ) {
161+ #if IS_USED (MODULE_SLIPDEV_CONFIG )
162+ /* try to create new frame */
163+ if (!crb_start_chunk (& dev -> rb_config )) {
164+ return ;
165+ }
166+ #endif
167+ dev -> state = SLIPDEV_STATE_CONFIG ;
168+ return ;
169+ }
170+
93171 /* ignore empty frame */
94172 if (byte == SLIPDEV_END ) {
95173 return ;
96174 }
97175
98- /* try to create new frame */
176+ /* try to create new ip frame */
99177 if (!crb_start_chunk (& dev -> rb )) {
100178 return ;
101179 }
@@ -198,8 +276,8 @@ void slipdev_write_bytes(uart_t uart, const uint8_t *data, size_t len)
198276
199277static int _check_state (slipdev_t * dev )
200278{
201- /* power states not supported when multiplexing stdio */
202- if (IS_USED (MODULE_SLIPDEV_STDIO )) {
279+ /* power states not supported when multiplexing stdio / configuration */
280+ if (IS_USED (MODULE_SLIPDEV_STDIO ) || IS_USED ( MODULE_SLIPDEV_CONFIG ) ) {
203281 return 0 ;
204282 }
205283
@@ -272,7 +350,7 @@ static void _isr(netdev_t *netdev)
272350 }
273351}
274352
275- #if !IS_USED (MODULE_SLIPDEV_STDIO )
353+ #if !( IS_USED (MODULE_SLIPDEV_STDIO ) || IS_USED ( MODULE_SLIPDEV_CONFIG ) )
276354static int _set_state (slipdev_t * dev , netopt_state_t state )
277355{
278356 if (IS_USED (MODULE_SLIPDEV_STDIO )) {
@@ -309,7 +387,7 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *value, size_t max_le
309387 return - ENOTSUP ;
310388 }
311389}
312- #endif /* !MODULE_SLIPDEV_STDIO */
390+ #endif /* !( MODULE_SLIPDEV_STDIO || MODULE_SLIPDEV_CONFIG) */
313391
314392static int _get (netdev_t * netdev , netopt_t opt , void * value , size_t max_len )
315393{
@@ -348,15 +426,69 @@ static const netdev_driver_t slip_driver = {
348426 .isr = _isr ,
349427 .get = _get ,
350428 .confirm_send = _confirm_send ,
351- #if IS_USED (MODULE_SLIPDEV_STDIO )
429+ #if ( IS_USED (MODULE_SLIPDEV_STDIO ) || IS_USED ( MODULE_SLIPDEV_CONFIG ) )
352430 .set = netdev_set_notsup ,
353431#else
354432 .set = _set ,
355433#endif
356434};
357435
436+ #if IS_USED (MODULE_SLIPDEV_CONFIG )
437+ static void * _coap_server_thread (void * arg )
438+ {
439+ static uint8_t buf [512 ];
440+ slipdev_t * dev = arg ;
441+ while (1 ) {
442+ thread_flags_wait_any (1 );
443+ size_t len ;
444+ while (crb_get_chunk_size (& dev -> rb_config , & len )) {
445+ crb_consume_chunk (& dev -> rb_config , buf , len );
446+
447+ /* Is the crc correct via residue(=0xF0B8) test */
448+ if (crc16_ccitt_fcs_update (SPECIAL_INIT_FCS , buf , len ) != 0xF0B8 ) {
449+ break ;
450+ }
451+
452+ /* cut off the FCS checksum at the end */
453+ size_t pktlen = len - 2 ;
454+
455+ coap_pkt_t pkt ;
456+ sock_udp_ep_t remote ;
457+ coap_request_ctx_t ctx = {
458+ .remote = & remote ,
459+ };
460+ if (coap_parse (& pkt , buf , pktlen ) < 0 ) {
461+ break ;
462+ }
463+ unsigned int res = 0 ;
464+ if ((res = coap_handle_req (& pkt , buf , sizeof (buf ), & ctx )) <= 0 ) {
465+ break ;
466+ }
467+
468+ uint16_t fcs_sum = crc16_ccitt_fcs_finish (SPECIAL_INIT_FCS , buf , res );
469+
470+ slipdev_lock ();
471+ slipdev_write_byte (dev -> config .uart , SLIPDEV_CONFIG_START );
472+ slipdev_write_bytes (dev -> config .uart , buf , res );
473+ slipdev_write_bytes (dev -> config .uart , (uint8_t * ) & fcs_sum , 2 );
474+ slipdev_write_byte (dev -> config .uart , SLIPDEV_END );
475+ slipdev_unlock ();
476+ }
477+ }
478+
479+ return NULL ;
480+ }
481+ #endif /* MODULE_SLIPDEV_CONFIG */
482+
358483void slipdev_setup (slipdev_t * dev , const slipdev_params_t * params , uint8_t index )
359484{
485+ #if IS_USED (MODULE_SLIPDEV_CONFIG )
486+ crb_init (& dev -> rb_config , dev -> rxmem_config , sizeof (dev -> rxmem_config ));
487+
488+ dev -> coap_server_pid = thread_create (coap_stack , sizeof (coap_stack ), THREAD_PRIORITY_MAIN - 1 ,
489+ THREAD_CREATE_STACKTEST , _coap_server_thread ,
490+ (void * )dev , "Slipmux CoAP server" );
491+ #endif
360492 /* set device descriptor fields */
361493 dev -> config = * params ;
362494 dev -> state = 0 ;
0 commit comments