aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2010-10-01 18:58:55 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2010-10-01 18:58:55 +0000
commit36bb415afd5dba7ce434976115c5899455690cd7 (patch)
tree50f7b632a389b3fb6120afb1de5fb01e29f2404c
parentbeb2c8145358bcd7b4494a7b636e378aa2a1ea95 (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.pd60
-rw-r--r--slipdec/slipdec.c407
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 */