Ethereal-dev: [Ethereal-dev] Serial infrared (SIR) [PATCH]
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Shaun Jackman <sjackman@xxxxxxxxx>
Date: Thu, 17 Jun 2004 00:03:59 -0700
What follows is a patch to add serial infrared (SIR) decoding to Ethereal. It is used, for example, by two instances of Palm OS Emulator (Pose) to communicate using IrDA. Now a couple of notes. I believe the checksum is the same as that in PPP. This common code could be factored out. I've tested this as a plugin. I'm not certain if it needs any work to compile statically. Finally, it has one known bug. The protocol uses an escape sequence to escape control characters. These escape sequences should be dealt with before the buffer is passed to the next dissector (IrLAP). I wasn't sure of the best way to handle this. Cheers, Shaun 2004-06-16 Shaun Jackman <sjackman@xxxxxxxxxx> * packet-sir.c: New. Dissect serial infrared (SIR) packets. * sir.h: New. SIR protocol constants. * fcs.c: New. SIR frame check sequencee (CRC-CCITT 16). * fcs.h: New. Prototypes for same. * moduleinfo.h: New. SIR module information. * Makefile.am: New. Build the SIR module. diff -ur sir-/Makefile.am sir/Makefile.am --- sir-/Makefile.am 2004-06-16 23:47:01.000000000 -0700 +++ sir/Makefile.am 2004-06-16 23:48:00.000000000 -0700 @@ -0,0 +1,6 @@ +plugin_LTLIBRARIES = sir.la +plugindir = @plugindir@ +sir_la_CFLAGS = -I$(pkgincludedir) +sir_la_LDFLAGS = -module -avoid-version +sir_la_SOURCES = fcs.c fcs.h packet-sir.c sir.h moduleinfo.h +CFLAGS += -Werror diff -ur sir-/fcs.c sir/fcs.c --- sir-/fcs.c 2004-06-16 23:47:01.000000000 -0700 +++ sir/fcs.c 2004-06-16 23:40:21.000000000 -0700 @@ -0,0 +1,67 @@ +/** Serial Infrared (SIR) frame check sequencee (CRC-CCITT 16). + * @author Shaun Jackman <sjackman@xxxxxxxxxx> + */ + +// prototypes +#include "fcs.h" + +// libc +#include <stdint.h> + + +/** CRC of each possible byte. It can be computed using the standard + * bit-at-a-time methods. The polynomial can be seen in entry 128, + * 0x8408. This corresponds to x^0 + x^5 + x^12. Add the implicit + * x^16, and you have the standard CRC-CCITT. + */ +const uint16_t +sir_crc16_table[] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + + +/** Calculates the FCS for the specified buffer. + * @param buf buffer + * @param len length of the buffer + * @return frame check sequence + */ +uint16_t +sir_fcs( const void* buf, unsigned len) +{ + const uint8_t* p = buf; + uint16_t fcs = SIR_FCS_INIT; + while( len--) + fcs = sir_fcs_incremental( fcs, *p++); + return ~fcs; +} diff -ur sir-/fcs.h sir/fcs.h --- sir-/fcs.h 2004-06-16 23:47:01.000000000 -0700 +++ sir/fcs.h 2004-06-15 15:05:39.000000000 -0700 @@ -0,0 +1,34 @@ +#ifndef __fcs_h__ +#define __fcs_h__ + + +// libc +#include <stdint.h> + + +/** Initial FCS value. */ +#define SIR_FCS_INIT 0xffff + +/** Good final FCS value. */ +#define SIR_FCS_GOOD 0xf0b8 + + +extern const uint16_t sir_crc16_table[256]; + + +/** Incrementally compute the FCS. + * @param fcs previous frame check sequence + * @param c next byte + * @return frame check sequence + */ +static inline uint16_t +sir_fcs_incremental( uint16_t fcs, uint8_t c) +{ + return (fcs >> 8) ^ sir_crc16_table[(fcs ^ c) & 0xff]; +} + + +uint16_t sir_fcs( const void* buf, unsigned len); + + +#endif diff -ur sir-/moduleinfo.h sir/moduleinfo.h --- sir-/moduleinfo.h 2004-06-16 23:47:01.000000000 -0700 +++ sir/moduleinfo.h 2004-06-14 15:44:26.000000000 -0700 @@ -0,0 +1,16 @@ +/* Included *after* config.h, in order to re-define these macros */ + +#ifdef PACKAGE +#undef PACKAGE +#endif + +/* Name of package */ +#define PACKAGE "sir" + + +#ifdef VERSION +#undef VERSION +#endif + +/* Version number of package */ +#define VERSION "0.1.0" diff -ur sir-/packet-sir.c sir/packet-sir.c --- sir-/packet-sir.c 2004-06-16 23:47:01.000000000 -0700 +++ sir/packet-sir.c 2004-06-16 23:49:34.000000000 -0700 @@ -0,0 +1,195 @@ +/** Decode IrDA Serial Infrared (SIR) wrapped packets. + * Known bugs: + * * This dissector does not handle control escape (0x7d) bytes. + * @author Shaun Jackman <sjackman@xxxxxxxxxx> + * @copyright Copyright 2004 Shaun Jackman + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "moduleinfo.h" +#include "plugins/plugin_api.h" + +#include <gmodule.h> + +#include "fcs.h" +#include "sir.h" + + +/** Serial infrared port. */ +#define SIR_PORT 6417 + + +#ifndef ENABLE_STATIC +/** Version string. */ +G_MODULE_EXPORT const gchar version[] = VERSION; +#endif + + +/** Protocol handles. */ +dissector_handle_t data_handle; +dissector_handle_t irda_handle; + +/** Protocol fields. */ +static int proto_sir = -1; +static int ett_sir = -1; +static int hf_sir_bof = -1; +static int hf_sir_ce = -1; +static int hf_sir_eof = -1; +static int hf_sir_fcs = -1; +static int hf_sir_fcs_bad = -1; +static int hf_sir_preamble = -1; + + +/** Dissects an SIR packet. */ +static void +dissect_sir( tvbuff_t* tvb, packet_info* pinfo, proto_tree* root) +{ + gint offset = 0; + while( tvb_length_remaining( tvb, offset) > 0) { + gint bof_offset = tvb_find_guint8( tvb, offset, -1, SIR_BOF); + guint preamble_len = bof_offset - offset; + gint eof_offset = bof_offset == -1 ? -1 : + tvb_find_guint8( tvb, bof_offset, -1, SIR_EOF); + gint data_offset = bof_offset + 1; + guint data_len = eof_offset - data_offset; + gint fcs_offset = -1; + if( bof_offset == -1 || eof_offset == -1) { + if( pinfo->can_desegment) { + pinfo->desegment_offset = + bof_offset == -1 ? 0 : bof_offset; + pinfo->desegment_len = 1; + } else { + fprintf( stderr, PACKAGE ": unable to desegment%s\n", + pinfo->noreassembly_reason); + } + return; + } + if( data_len >= 2) { + data_len -= 2; + fcs_offset = eof_offset - 2; + } + if( root) { + guint len = eof_offset - offset + 1; + proto_tree* ti = proto_tree_add_protocol_format( root, + proto_sir, tvb, offset, len, + "Serial Infrared, Len: %d", data_len); + proto_tree* tree = proto_item_add_subtree( ti, ett_sir); + if( preamble_len > 0) + proto_tree_add_item( tree, hf_sir_preamble, tvb, + offset, preamble_len, FALSE); + proto_tree_add_item( tree, hf_sir_bof, tvb, + bof_offset, 1, FALSE); + if( fcs_offset != -1) { + guint16 actual_fcs = tvb_get_letohs( tvb, fcs_offset); + guint16 calculated_fcs = sir_fcs( tvb_get_ptr( + tvb, data_offset, data_len), data_len); + if( calculated_fcs == actual_fcs) { + proto_tree_add_uint_format( tree, hf_sir_fcs, + tvb, fcs_offset, 2, actual_fcs, + "Frame check sequence: 0x%04x (correct)", + actual_fcs); + } else { + proto_tree_add_boolean_hidden( tree, + hf_sir_fcs_bad, tvb, + fcs_offset, 2, TRUE); + proto_tree_add_uint_format( tree, hf_sir_fcs, + tvb, fcs_offset, 2, actual_fcs, + "Frame check sequence: 0x%04x " + "(incorrect, should be 0x%04x)", + actual_fcs, calculated_fcs); + } + } + proto_tree_add_item( tree, hf_sir_eof, tvb, + eof_offset, 1, FALSE); + } + { + tvbuff_t* data_tvb = tvb_new_subset( tvb, + data_offset, data_len, data_len); + call_dissector( irda_handle, data_tvb, pinfo, root); + offset = eof_offset + 1; + } + } +} + + +/** Registers this dissector with the parent dissector. */ +static void +proto_reg_handoff_sir( void) +{ + dissector_add( "tcp.port", SIR_PORT, find_dissector( "sir")); + + data_handle = find_dissector( "data"); + irda_handle = find_dissector( "irda"); + if( irda_handle == 0) { + irda_handle = data_handle; + fputs( PACKAGE ": Unable to find IrDA dissector.\n", stderr); + } +} + + +/** Initializes this protocol. */ +static void +proto_register_sir( void) +{ + static gint* ett[] = { &ett_sir }; + + static hf_register_info hf_sir[] = { + { &hf_sir_bof, + { "Beginning of frame", "sir.bof", + FT_UINT8, BASE_HEX, NULL, 0, + "", HFILL }}, + { &hf_sir_ce, + { "Command escape", "sir.ce", + FT_UINT8, BASE_HEX, NULL, 0, + "", HFILL }}, + { &hf_sir_eof, + { "End of frame", "sir.eof", + FT_UINT8, BASE_HEX, NULL, 0, + "", HFILL }}, + { &hf_sir_fcs, + { "Frame check sequence", "sir.fcs", + FT_UINT16, BASE_HEX, NULL, 0, + "", HFILL }}, + { &hf_sir_fcs_bad, + { "Bad frame check sequence", "sir.fcs_bad", + FT_BOOLEAN, BASE_NONE, NULL, 0, + "", HFILL }}, + { &hf_sir_preamble, + { "Preamble", "sir.preamble", + FT_BYTES, BASE_NONE, NULL, 0, + "", HFILL }}, + }; + + proto_sir = proto_register_protocol( + "Serial Infrared", "SIR", "sir"); + register_dissector( "sir", dissect_sir, proto_sir); + proto_register_subtree_array( ett, array_length( ett)); + proto_register_field_array( + proto_sir, hf_sir, array_length( hf_sir)); +} + + +#ifndef __ETHEREAL_STATIC__ + +/** Registers this plugin. */ +G_MODULE_EXPORT void +plugin_reg_handoff( void) +{ + proto_reg_handoff_sir(); +} + + +/** Initializes this plugin. */ +G_MODULE_EXPORT void +plugin_init( plugin_address_table_t* pat) +{ + (void)pat; + plugin_address_table_init( pat); + if( proto_sir == -1) + proto_register_sir(); +} + + +#endif diff -ur sir-/sir.h sir/sir.h --- sir-/sir.h 2004-06-16 23:47:01.000000000 -0700 +++ sir/sir.h 2004-06-14 16:50:49.000000000 -0700 @@ -0,0 +1,18 @@ +#ifndef __sir_h__ +#define __sir_h__ + + +/** Beginning of frame. */ +#define SIR_BOF 0xc0 + +/** End of frame. */ +#define SIR_EOF 0xc1 + +/** Control escape. */ +#define SIR_CE 0x7d + +/** Escapes this character. */ +#define SIR_ESCAPE(x) ((x)^0x20) + + +#endif
- Follow-Ups:
- Re: [Ethereal-dev] Serial infrared (SIR) [PATCH]
- From: Guy Harris
- Re: [Ethereal-dev] Serial infrared (SIR) [PATCH]
- Prev by Date: [Ethereal-dev] [TCP Previous segment lost] on loopback device
- Next by Date: Re: [Ethereal-dev] packet-cpfi.c - enhancements
- Previous by thread: [Ethereal-dev] [TCP Previous segment lost] on loopback device
- Next by thread: Re: [Ethereal-dev] Serial infrared (SIR) [PATCH]
- Index(es):