diff options
author | Martin Peach <mrpeach@users.sourceforge.net> | 2010-10-01 18:58:55 +0000 |
---|---|---|
committer | Martin Peach <mrpeach@users.sourceforge.net> | 2010-10-01 18:58:55 +0000 |
commit | 36bb415afd5dba7ce434976115c5899455690cd7 (patch) | |
tree | 50f7b632a389b3fb6120afb1de5fb01e29f2404c | |
parent | beb2c8145358bcd7b4494a7b636e378aa2a1ea95 (diff) |
Fixed bugs where incomplete packets with escapes were not decoded correctly. Added a help patch.
svn path=/trunk/externals/mrpeach/; revision=14183
-rw-r--r-- | slipdec/slipdec-help.pd | 60 | ||||
-rw-r--r-- | slipdec/slipdec.c | 407 |
2 files changed, 265 insertions, 202 deletions
diff --git a/slipdec/slipdec-help.pd b/slipdec/slipdec-help.pd new file mode 100644 index 0000000..ff84873 --- /dev/null +++ b/slipdec/slipdec-help.pd @@ -0,0 +1,60 @@ +#N canvas 167 296 901 442 10;
+#X obj 388 325 print decoded;
+#X msg 319 159 192 192 192 192 192;
+#X floatatom 339 182 5 0 0 0 - - -;
+#X obj 382 238 cnv 15 60 30 empty empty empty 20 12 0 14 -4034 -66577
+0;
+#X text -57 298 The motivation behind SLIP is the need to determine
+the boundaries of a packet when it is received one byte at a time \,
+as with a serial channel. Bytes are integers between 0 and 255;
+#X msg 185 25 verbosity \$1;
+#X obj 185 6 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X text -57 355 SLIP (RFC 1055) is a simple encoding that prefixes
+each packet with 192 \, and replaces 192s inside the packet with 219
+followed by 220 Any 219 will be replaced with 219 and 221 The packet
+ends with 192;
+#X text 443 160 Null packets are invisible;
+#X obj 427 274 print valid;
+#X text -57 193 Note that the SLIP specification limits the maximum
+packet size to 1006...;
+#X obj 388 245 slipdec;
+#X text -57 221 ...but a float argument to slipdec or slipenc will
+set another maximum packet size;
+#X msg 229 69 192 \, 1.33 \, 192;
+#X text 335 45 This should give 1 192;
+#X text 321 69 Only bytes are permitted;
+#X msg 275 115 192 219 5 6 7 192;
+#X msg 253 93 1 43 5 6 7 192;
+#X text 348 92 Missing 192 at start is OK;
+#X text -58 139 [slipdec];
+#X text 548 404 Author: Martin Peach \, 2010/10/01;
+#X msg 205 45 192 1 \, 219 \, 220 \, 192;
+#X msg 297 137 1 25 5 6 7;
+#X text -57 257 Input can be any combination of float and list of floats
+as long as they are integers on [0...255];
+#X text 385 115 Bad escapes are invalid;
+#X text 368 136 Unterminated input will be accumulated until end is
+received;
+#X text 636 368 See also:;
+#X obj 695 370 slipenc;
+#X text -58 153 Decodes bytes from SLIP to raw. Useful for receiving
+OSC via [comport].;
+#X text 427 290 Right outlet is one whenever a valid packet is output
+\, zero if packet could not be decoded (bad packets are not output).
+;
+#X text 389 341 Left outlet gives lists of decoded bytes whenever valid
+= 1;
+#X text 267 24 Verbosity might be useful if things don't seem to be
+working;
+#X connect 1 0 11 0;
+#X connect 2 0 11 0;
+#X connect 5 0 11 0;
+#X connect 6 0 5 0;
+#X connect 11 0 0 0;
+#X connect 11 1 9 0;
+#X connect 13 0 11 0;
+#X connect 16 0 11 0;
+#X connect 17 0 11 0;
+#X connect 21 0 11 0;
+#X connect 22 0 11 0;
diff --git a/slipdec/slipdec.c b/slipdec/slipdec.c index e654b24..ce80cce 100644 --- a/slipdec/slipdec.c +++ b/slipdec/slipdec.c @@ -1,50 +1,49 @@ -/* slipdec.c 20100513 Martin Peach */
-/* decode a list of SLIP-encoded bytes */
-#include "m_pd.h"
-
-/* -------------------------- slipdec -------------------------- */
-#ifndef _SLIPCODES
-/* SLIP special character codes */
-#define SLIP_END 0300 /* indicates end of packet */
-#define SLIP_ESC 0333 /* indicates byte stuffing */
-#define SLIP_ESC_END 0334 /* SLIP_ESC SLIP_ESC_END means SLIP_END data byte */
-#define SLIP_ESC_ESC 0335 /* SLIP_ESC SLIP_ESC_ESC means SLIP_ESC data byte */
-#define MAX_SLIP 1006 /* maximum SLIP packet size */
-#define _SLIPCODES
-#endif // _SLIPCODES
-
-static t_class *slipdec_class;
-
-typedef struct _slipdec
-{
- t_object x_obj;
- t_outlet *x_slipdec_out;
- t_outlet *x_status_out;
- t_atom *x_slip_buf;
- t_int x_slip_length;
+/* slipdec.c 20100513 Martin Peach */ +/* decode a list of SLIP-encoded bytes */ +#include "m_pd.h" + +/* -------------------------- slipdec -------------------------- */ +#ifndef _SLIPCODES +/* SLIP special character codes */ +#define SLIP_END 0300 /* decimal 192 indicates end of packet */ +#define SLIP_ESC 0333 /* decimal 219 indicates byte stuffing */ +#define SLIP_ESC_END 0334 /* decimal 220 SLIP_ESC_END means SLIP_END as data byte */ +#define SLIP_ESC_ESC 0335 /* decimal 221 SLIP_ESC_ESC means SLIP_ESC as data byte */ +#define MAX_SLIP 1006 /* maximum SLIP packet size */ +#define _SLIPCODES +#endif /* _SLIPCODES */ + +static t_class *slipdec_class; + +typedef struct _slipdec +{ + t_object x_obj; + t_outlet *x_slipdec_out; + t_outlet *x_status_out; + t_atom *x_slip_buf; + t_int x_slip_length; t_int x_slip_max_length; - t_int x_packet_index;
- t_int x_valid_SLIP;
- t_int x_esced;
- t_int x_verbose;
-} t_slipdec;
-
-static void *slipdec_new(t_symbol *s, int argc, t_atom *argv);
+ t_int x_valid_SLIP; + t_int x_esced; + t_int x_verbose; +} t_slipdec; + +static void *slipdec_new(t_symbol *s, int argc, t_atom *argv); static void slipdec_dump(t_slipdec *x, int dosend); -static void slipdec_list(t_slipdec *x, t_symbol *s, int ac, t_atom *av);
-static void slipdec_float(t_slipdec *x, t_float f);
-static void slipdec_verbosity(t_slipdec *x, t_float f);
-static void slipdec_free(t_slipdec *x);
-void slipdec_setup(void);
-
-static void *slipdec_new(t_symbol *s, int argc, t_atom *argv)
-{
- int i;
+static void slipdec_list(t_slipdec *x, t_symbol *s, int ac, t_atom *av); +static void slipdec_float(t_slipdec *x, t_float f); +static void slipdec_verbosity(t_slipdec *x, t_float f); +static void slipdec_free(t_slipdec *x); +void slipdec_setup(void); + +static void *slipdec_new(t_symbol *s, int argc, t_atom *argv) +{ + int i; t_slipdec *x = (t_slipdec *)pd_new(slipdec_class); if (x == NULL) return x; - x->x_slip_max_length = MAX_SLIP;// default unless a float argument is given
+ x->x_slip_max_length = MAX_SLIP;// default unless a float argument is given for (i = 0; i < argc; ++i) { if (argv[i].a_type == A_FLOAT) @@ -55,177 +54,181 @@ static void *slipdec_new(t_symbol *s, int argc, t_atom *argv) } } - x->x_slip_buf = (t_atom *)getbytes(sizeof(t_atom)*x->x_slip_max_length);
- if(x->x_slip_buf == NULL)
- {
- error("slipdec: unable to allocate %lu bytes for x_slip_buf", (long)sizeof(t_atom)*x->x_slip_max_length);
- return NULL;
- }
- /* init the slip buf atoms to float type */
- for (i = 0; i < x->x_slip_max_length; ++i) x->x_slip_buf[i].a_type = A_FLOAT;
- x->x_slipdec_out = outlet_new(&x->x_obj, &s_list);
- x->x_status_out = outlet_new(&x->x_obj, &s_anything);
- x->x_packet_index = 0;
- x->x_valid_SLIP = 1;
- return (x);
-}
+ x->x_slip_buf = (t_atom *)getbytes(sizeof(t_atom)*x->x_slip_max_length); + if(x->x_slip_buf == NULL) + { + error("slipdec: unable to allocate %lu bytes for x_slip_buf", (long)sizeof(t_atom)*x->x_slip_max_length); + return NULL; + } + /* init the slip buf atoms to float type */ + for (i = 0; i < x->x_slip_max_length; ++i) x->x_slip_buf[i].a_type = A_FLOAT; + x->x_slipdec_out = outlet_new(&x->x_obj, &s_list); + x->x_status_out = outlet_new(&x->x_obj, &s_anything); + x->x_valid_SLIP = 1; + return (x); +} static void slipdec_dump(t_slipdec *x, int dosend) -{
+{ + outlet_float(x->x_status_out, x->x_valid_SLIP); if(dosend) - {
- if ((0 != x->x_valid_SLIP) && (x->x_slip_length > 0))
- outlet_list(x->x_slipdec_out, &s_list, x->x_slip_length, x->x_slip_buf);
- }
- - x->x_slip_length = x->x_esced = x->x_packet_index = 0;
- x->x_valid_SLIP = 1;
-}
-
-static void slipdec_list(t_slipdec *x, t_symbol *s, int ac, t_atom *av)
-{
- /* SLIP decode a list of bytes */
- float f;
- int i = 0, c;
- - /* x_slip_length will be non-zero if an incomplete packet is in the buffer */
+ { + if ((0 != x->x_valid_SLIP) && (x->x_slip_length > 0)) + outlet_list(x->x_slipdec_out, &s_list, x->x_slip_length, x->x_slip_buf); + } + + x->x_slip_length = x->x_esced = 0; + x->x_valid_SLIP = 1; +} + +static void slipdec_list(t_slipdec *x, t_symbol *s, int ac, t_atom *av) +{ + /* SLIP decode a list of bytes */ + float f; + int i, c; + + if (x->x_verbose) post ("slipdec_list: buffer length %d, esc = %d", x->x_slip_length, x->x_esced); + /* x_slip_length will be non-zero if an incomplete packet is in the buffer */ if ((ac + x->x_slip_length) > x->x_slip_max_length) { - pd_error (x, "slipdec_list: input packet longer than %d", x->x_slip_max_length);
- x->x_slip_length = x->x_esced = x->x_packet_index = 0;
+ pd_error (x, "slipdec_list: input packet longer than %d", x->x_slip_max_length); + x->x_valid_SLIP = 0; /* not valid SLIP */ + slipdec_dump(x,0);// reset return; - }
- /* for each byte in the packet, send the appropriate character sequence */
- for(; ((i < ac) && (x->x_slip_length < x->x_slip_max_length)); ++i)
- {
- /* check each atom for byteness */
- f = atom_getfloat(&av[i]);
- c = (((int)f) & 0x0FF);
- if (c != f)
- {
- /* abort, input list needs to be fixed before this is gonna wuk */
- pd_error (x, "slipdec: input %d out of range [0..255]", f);
- return;
- }
- if(SLIP_END == c)
- {
- if (x->x_verbose) post ("slipdec_list: SLIP_END packet index is %d", x->x_packet_index);
- /* If it's the beginning of a packet, ignore it */
+ } + /* for each byte in the packet, send the appropriate character sequence */ + for(i = 0; ((i < ac) && (x->x_slip_length < x->x_slip_max_length)); ++i) + { + /* check each atom for byteness */ + f = atom_getfloat(&av[i]); + c = (((int)f) & 0x0FF); + if (c != f) + { + /* abort, input list needs to be fixed before this is gonna wuk */ + pd_error (x, "slipdec: input %d out of range [0..255]", f); + x->x_valid_SLIP = 0; /* not valid SLIP */ + slipdec_dump(x,0);// reset + return; + } + if(SLIP_END == c) + { + if (x->x_verbose) post ("slipdec_list: SLIP_END at %d", x->x_slip_length); + /* If it's the beginning of a packet, ignore it */ if (x->x_slip_length) - {
- if (x->x_verbose) post ("slipdec_list: end of packet");
- /* send the packet */
- slipdec_dump(x, 1);
- }
- continue;
- }
- if (SLIP_ESC == c)
- {
- if (x->x_verbose) post ("slipdec_list: SLIP_ESC %f = %d", f, c);
- x->x_esced = 1;
- continue;
- }
- if (1 == x->x_esced)
- {
- if (SLIP_ESC_END == c) c = SLIP_END;
- else if (SLIP_ESC_ESC == c) c = SLIP_ESC;
- else x->x_valid_SLIP = 0; /* not valid SLIP */
- if (x->x_verbose) post ("slipdec_list: ESCED %f = %d", f, c);
- x->x_esced = 0;
- }
- /* Add the character to the list */
- x->x_slip_buf[x->x_slip_length++].a_w.w_float = c;
- }
- if (0 != x->x_slip_length)
- {
- if(SLIP_END != c) x->x_valid_SLIP = 0;
- outlet_float(x->x_status_out, x->x_valid_SLIP);
- if (0 != x->x_valid_SLIP) outlet_list(x->x_slipdec_out, &s_list, x->x_slip_length, x->x_slip_buf);
- x->x_slip_length = x->x_esced = x->x_packet_index = 0;
- x->x_valid_SLIP = 1;
- /* any remaining data in the list is ignored for now... */ - if (i < ac-1) post("slipdec_list: dropped %d bytes after packet", ac-1-i); - }
-}
-
-static void slipdec_float(t_slipdec *x, t_float f)
-{
- /* SLIP decode a byte */
- int c;
- /* for each byte in the packet, send the appropriate character sequence */
- /* check each atom for byteness */
- c = (((int)f) & 0x0FF);
- if (c != f)
- {
- /* abort, input list needs to be fixed before this is gonna wuk */
- pd_error (x, "slipdec: input %d out of range [0..255]", f);
- x->x_slip_length = x->x_esced = x->x_packet_index = 0;
- x->x_valid_SLIP = 1;
- return;
- }
- if(SLIP_END == c)
- {
- if (x->x_verbose) post ("slipdec_float: SLIP_END packet index is %d", x->x_packet_index);
- /* If it's the beginning of a packet, ignore it */
- if (0 == x->x_packet_index) return;
- /* send the packet */
- else
- {
- if (x->x_verbose) post ("slipdec_float: end of packet");
- outlet_float(x->x_status_out, x->x_valid_SLIP);
- if ((0 != x->x_slip_length) && (0 != x->x_valid_SLIP))
- outlet_list(x->x_slipdec_out, &s_list, x->x_slip_length, x->x_slip_buf);
- x->x_slip_length = x->x_esced = x->x_packet_index = 0;
- x->x_valid_SLIP = 1;
- return;
- }
- }
- if (SLIP_ESC == c)
- {
- if (x->x_verbose) post ("slipdec_float: SLIP_ESC %f = %d", f, c);
- x->x_esced = 1;
- return;
- }
- if (1 == x->x_esced)
- {
- if (SLIP_ESC_END == c) c = SLIP_END;
- else if (SLIP_ESC_ESC == c) c = SLIP_ESC;
- else x->x_valid_SLIP = 0; /* not valid SLIP */
- if (x->x_verbose) post ("slipdec_float: ESCED %f = %d", f, c);
- x->x_esced = 0;
- }
- /* Add the character to the list */
- if (0 == x->x_packet_index++) x->x_slip_length = 0;
+ { + if (x->x_verbose) post ("slipdec_list: end of packet"); + /* send the packet */ + slipdec_dump(x, 1); + } + continue; + } + if (SLIP_ESC == c) + { + if (x->x_verbose) post ("slipdec_list: SLIP_ESC %f = %d", f, c); + x->x_esced = 1; + continue; + } + if (1 == x->x_esced) + { + if (SLIP_ESC_END == c) c = SLIP_END; + else if (SLIP_ESC_ESC == c) c = SLIP_ESC; + else + { + pd_error (x, "slipdec_list: SLIP_ESC not followed by 220 or 221 (%d)", c); + x->x_valid_SLIP = 0; /* not valid SLIP */ + slipdec_dump(x,0);/* reset */ + return; + } + x->x_esced = 0; + } + /* Add the character to the buffer */ + if (x->x_verbose) post ("slipdec_list: adding character %d to buffer[%d]", c, x->x_slip_length); + x->x_slip_buf[x->x_slip_length++].a_w.w_float = c; + } +} + +static void slipdec_float(t_slipdec *x, t_float f) +{ + /* SLIP decode a byte */ + int c; + + if (x->x_verbose) post ("slipdec_float: buffer length %d, esc = %d", x->x_slip_length, x->x_esced); + /* for each byte in the packet, send the appropriate character sequence */ + /* check each atom for byteness */ + c = (((int)f) & 0x0FF); + if (c != f) + { + /* abort, input list needs to be fixed before this is gonna wuk */ + pd_error (x, "slipdec: input %d out of range [0..255]", f); + x->x_valid_SLIP = 0; /* not valid SLIP */ + slipdec_dump(x,0);/* reset */ + return; + } + if(SLIP_END == c) + { + if (x->x_verbose) post ("slipdec_float: SLIP_END at %d", x->x_slip_length); + /* If it's the beginning of a packet, ignore it */ + if (0 == x->x_slip_length) return; + /* send the packet */ + else + { + if (x->x_verbose) post ("slipdec_float: end of packet"); + slipdec_dump(x, 1); + return; + } + } + if (SLIP_ESC == c) + { + if (x->x_verbose) post ("slipdec_float: SLIP_ESC %f = %d", f, c); + x->x_esced = 1; + return; + } + if (1 == x->x_esced) + { + if (SLIP_ESC_END == c) c = SLIP_END; + else if (SLIP_ESC_ESC == c) c = SLIP_ESC; + else + { + x->x_valid_SLIP = 0; /* not valid SLIP */ + slipdec_dump(x,0);/* reset */ + pd_error (x, "slipdec_float: SLIP_ESC not followed by 220 or 221 (%d)", c); + return; + } + if (x->x_verbose) post ("slipdec_float: ESCED %f = %d", f, c); + x->x_esced = 0; + } + /* Add the character to the buffer */ if (x->x_slip_length < x->x_slip_max_length) { + if (x->x_verbose) post ("slipdec_float: adding character %d to buffer[%d]", c, x->x_slip_length); x->x_slip_buf[x->x_slip_length++].a_w.w_float = c; } else { - pd_error (x, "slipdec: input packet longer than %d", x->x_slip_length);
- x->x_slip_length = x->x_esced = x->x_packet_index = 0;
- }
-}
-
-static void slipdec_verbosity(t_slipdec *x, t_float f)
-{
- x->x_verbose = (0 != f)?1:0;
-}
-
-static void slipdec_free(t_slipdec *x)
-{
- if (x->x_slip_buf != NULL) freebytes((void *)x->x_slip_buf, sizeof(t_atom)*x->x_slip_max_length);
-}
-
-void slipdec_setup(void)
-{
- slipdec_class = class_new(gensym("slipdec"),
- (t_newmethod)slipdec_new, (t_method)slipdec_free,
- sizeof(t_slipdec), 0, A_GIMME, 0);
- class_addlist(slipdec_class, slipdec_list);
- class_addfloat(slipdec_class, slipdec_float);
- class_addmethod(slipdec_class, (t_method)slipdec_verbosity, gensym("verbosity"), A_FLOAT, 0);
- class_sethelpsymbol(slipdec_class, gensym("slipenc")); /* use slipenc-help.pd */
-}
-
-/* fin slipdec.c*/
+ pd_error (x, "slipdec: input packet longer than %d", x->x_slip_length); + x->x_valid_SLIP = 0; /* not valid SLIP */ + slipdec_dump(x,0);/* reset */ + } +} + +static void slipdec_verbosity(t_slipdec *x, t_float f) +{ + x->x_verbose = (0 != f)?1:0; +} + +static void slipdec_free(t_slipdec *x) +{ + if (x->x_slip_buf != NULL) freebytes((void *)x->x_slip_buf, sizeof(t_atom)*x->x_slip_max_length); +} + +void slipdec_setup(void) +{ + slipdec_class = class_new(gensym("slipdec"), + (t_newmethod)slipdec_new, (t_method)slipdec_free, + sizeof(t_slipdec), 0, A_GIMME, 0); + class_addlist(slipdec_class, slipdec_list); + class_addfloat(slipdec_class, slipdec_float); + class_addmethod(slipdec_class, (t_method)slipdec_verbosity, gensym("verbosity"), A_FLOAT, 0); +} + +/* fin slipdec.c */ |