2 * Routines for IrCOMM dissection
3 * By Jan Kiszka <jan.kiszka@web.de>
4 * Copyright 2003 Jan Kiszka
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@unicom.net>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include "moduleinfo.h"
39 #include <epan/packet.h>
40 #include <epan/proto.h>
42 #ifdef NEED_SNPRINTF_H
43 # include "snprintf.h"
49 * http://www.irda.org/standards/specifications.asp
51 * for various IrDA specifications.
54 #include "irda-appl.h"
57 /* Parameters common to all service types */
58 #define IRCOMM_SERVICE_TYPE 0x00
59 #define IRCOMM_PORT_TYPE 0x01 /* Only used in LM-IAS */
60 #define IRCOMM_PORT_NAME 0x02 /* Only used in LM-IAS */
62 /* Parameters for both 3 wire and 9 wire */
63 #define IRCOMM_DATA_RATE 0x10
64 #define IRCOMM_DATA_FORMAT 0x11
65 #define IRCOMM_FLOW_CONTROL 0x12
66 #define IRCOMM_XON_XOFF 0x13
67 #define IRCOMM_ENQ_ACK 0x14
68 #define IRCOMM_LINE_STATUS 0x15
69 #define IRCOMM_BREAK 0x16
71 /* Parameters for 9 wire */
72 #define IRCOMM_DTE 0x20
73 #define IRCOMM_DCE 0x21
74 #define IRCOMM_POLL 0x22
76 /* Service type (details) */
77 #define IRCOMM_3_WIRE_RAW 0x01
78 #define IRCOMM_3_WIRE 0x02
79 #define IRCOMM_9_WIRE 0x04
80 #define IRCOMM_CENTRONICS 0x08
82 /* Port type (details) */
83 #define IRCOMM_SERIAL 0x01
84 #define IRCOMM_PARALLEL 0x02
86 /* Data format (details) */
87 #define IRCOMM_WSIZE_5 0x00
88 #define IRCOMM_WSIZE_6 0x01
89 #define IRCOMM_WSIZE_7 0x02
90 #define IRCOMM_WSIZE_8 0x03
92 #define IRCOMM_1_STOP_BIT 0x00
93 #define IRCOMM_2_STOP_BIT 0x04 /* 1.5 if char len 5 */
95 #define IRCOMM_PARITY_DISABLE 0x00
96 #define IRCOMM_PARITY_ENABLE 0x08
98 #define IRCOMM_PARITY_ODD 0x00
99 #define IRCOMM_PARITY_EVEN 0x10
100 #define IRCOMM_PARITY_MARK 0x20
101 #define IRCOMM_PARITY_SPACE 0x30
104 #define IRCOMM_XON_XOFF_IN 0x01
105 #define IRCOMM_XON_XOFF_OUT 0x02
106 #define IRCOMM_RTS_CTS_IN 0x04
107 #define IRCOMM_RTS_CTS_OUT 0x08
108 #define IRCOMM_DSR_DTR_IN 0x10
109 #define IRCOMM_DSR_DTR_OUT 0x20
110 #define IRCOMM_ENQ_ACK_IN 0x40
111 #define IRCOMM_ENQ_ACK_OUT 0x80
114 #define IRCOMM_OVERRUN_ERROR 0x02
115 #define IRCOMM_PARITY_ERROR 0x04
116 #define IRCOMM_FRAMING_ERROR 0x08
118 /* DTE (Data terminal equipment) line settings */
119 #define IRCOMM_DELTA_DTR 0x01
120 #define IRCOMM_DELTA_RTS 0x02
121 #define IRCOMM_DTR 0x04
122 #define IRCOMM_RTS 0x08
124 /* DCE (Data communications equipment) line settings */
125 #define IRCOMM_DELTA_CTS 0x01 /* Clear to send has changed */
126 #define IRCOMM_DELTA_DSR 0x02 /* Data set ready has changed */
127 #define IRCOMM_DELTA_RI 0x04 /* Ring indicator has changed */
128 #define IRCOMM_DELTA_CD 0x08 /* Carrier detect has changed */
129 #define IRCOMM_CTS 0x10 /* Clear to send is high */
130 #define IRCOMM_DSR 0x20 /* Data set ready is high */
131 #define IRCOMM_RI 0x40 /* Ring indicator is high */
132 #define IRCOMM_CD 0x80 /* Carrier detect is high */
133 #define IRCOMM_DCE_DELTA_ANY 0x0f
135 /* Initialize the subtree pointers */
136 static gint ett_ircomm = -1;
137 static gint ett_ircomm_ctrl = -1;
139 #define MAX_PARAMETERS 32
140 static gint ett_param[MAX_IAP_ENTRIES * MAX_PARAMETERS];
143 static int proto_ircomm = -1;
144 static int hf_ircomm_param = -1;
145 static int hf_param_pi = -1;
146 static int hf_param_pl = -1;
147 static int hf_param_pv = -1;
148 static int hf_control = -1;
149 static int hf_control_len = -1;
151 static gboolean dissect_ircomm_parameters(tvbuff_t* tvb, unsigned offset, packet_info* pinfo,
152 proto_tree* tree, unsigned list_index, guint8 attr_type);
153 static gboolean dissect_ircomm_ttp_lsap(tvbuff_t* tvb, unsigned offset, packet_info* pinfo,
154 proto_tree* tree, unsigned list_index, guint8 attr_type);
155 static gboolean dissect_ircomm_lmp_lsap(tvbuff_t* tvb, unsigned offset, packet_info* pinfo,
156 proto_tree* tree, unsigned list_index, guint8 attr_type);
158 ias_attr_dissector_t ircomm_attr_dissector[] = {
159 /* IrDA:IrCOMM attribute dissectors */
160 { "Parameters", dissect_ircomm_parameters },
161 { "IrDA:TinyTP:LsapSel", dissect_ircomm_ttp_lsap },
165 ias_attr_dissector_t irlpt_attr_dissector[] = {
166 /* IrLPT attribute dissectors */
167 { "IrDA:IrLMP:LsapSel", dissect_ircomm_lmp_lsap },
168 { "IrDA:IrLMP:LSAPSel", dissect_ircomm_lmp_lsap }, /* according to IrCOMM V1.0, p25 */
174 * Dissect the cooked IrCOMM protocol
176 static void dissect_cooked_ircomm(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
182 if (tvb_length(tvb) == 0)
185 /* Make entries in Protocol column on summary display */
186 if (check_col(pinfo->cinfo, COL_PROTOCOL))
187 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrCOMM");
189 clen = tvb_get_guint8(tvb, offset);
191 if (check_col(pinfo->cinfo, COL_INFO))
194 unsigned len = tvb_length(tvb) - 1 - clen;
198 sprintf(buf, "Clen=%d, UserData: %d byte%s", clen, len, (len > 1)? "s": "");
200 sprintf(buf, "Clen=%d", clen);
201 col_add_str(pinfo->cinfo, COL_INFO, buf);
206 /* create display subtree for the protocol */
207 proto_item* ti = proto_tree_add_item(root, proto_ircomm, tvb, 0, -1, FALSE);
208 proto_tree* tree = proto_item_add_subtree(ti, ett_ircomm);
210 proto_tree* ctrl_tree;
213 ti = proto_tree_add_item(tree, hf_control, tvb, 0, clen + 1, FALSE);
214 ctrl_tree = proto_item_add_subtree(ti, ett_ircomm_ctrl);
215 proto_tree_add_item(ctrl_tree, hf_control_len, tvb, offset, 1, FALSE);
218 tvbuff_t *cvalue = tvb_new_subset(tvb, offset, clen, clen);
219 call_dissector(data_handle, cvalue, pinfo, ctrl_tree);
223 tvb = tvb_new_subset(tvb, offset, -1, -1);
224 call_dissector(data_handle, tvb, pinfo, tree);
230 * Dissect the raw IrCOMM/IrLPT protocol
232 static void dissect_raw_ircomm(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
234 unsigned len = tvb_length(tvb);
240 /* Make entries in Protocol column on summary display */
241 if (check_col(pinfo->cinfo, COL_PROTOCOL))
242 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrCOMM");
244 if (check_col(pinfo->cinfo, COL_INFO))
249 sprintf(buf, "User Data: %d byte%s", len, (len > 1)? "s": "");
250 col_add_str(pinfo->cinfo, COL_INFO, buf);
255 /* create display subtree for the protocol */
256 proto_item* ti = proto_tree_add_item(root, proto_ircomm, tvb, 0, -1, FALSE);
257 proto_tree* tree = proto_item_add_subtree(ti, ett_ircomm);
259 call_dissector(data_handle, tvb, pinfo, tree);
265 * Dissect IrCOMM IAS "Parameters" attribute
267 static gboolean dissect_ircomm_parameters(tvbuff_t* tvb, unsigned offset, packet_info* pinfo _U_,
268 proto_tree* tree, unsigned list_index, guint8 attr_type)
278 if (!check_iap_octet_result(tvb, tree, offset, "Parameters", attr_type))
283 len = tvb_get_ntohs(tvb, offset) + offset + 2;
288 guint8 p_len = tvb_get_guint8(tvb, offset + 1);
291 ti = proto_tree_add_item(tree, hf_ircomm_param, tvb, offset, p_len + 2, FALSE);
292 p_tree = proto_item_add_subtree(ti, ett_param[list_index * MAX_PARAMETERS + n]);
296 switch (tvb_get_guint8(tvb, offset))
298 case IRCOMM_SERVICE_TYPE:
299 proto_item_append_text(ti, ": Service Type (");
301 pv = tvb_get_guint8(tvb, offset+2);
302 if (pv & IRCOMM_3_WIRE_RAW)
303 strcat(buf, ", 3-Wire raw");
304 if (pv & IRCOMM_3_WIRE)
305 strcat(buf, ", 3-Wire");
306 if (pv & IRCOMM_9_WIRE)
307 strcat(buf, ", 9-Wire");
308 if (pv & IRCOMM_CENTRONICS)
309 strcat(buf, ", Centronics");
313 proto_item_append_text(ti, buf+2);
317 case IRCOMM_PORT_TYPE:
318 proto_item_append_text(ti, ": Port Type (");
320 pv = tvb_get_guint8(tvb, offset+2);
321 if (pv & IRCOMM_SERIAL)
322 strcat(buf, ", serial");
323 if (pv & IRCOMM_PARALLEL)
324 strcat(buf, ", parallel");
328 proto_item_append_text(ti, buf+2);
332 case IRCOMM_PORT_NAME:
333 /* XXX - the IrCOMM V1.0 spec says this "Normally
334 human readable text, but not required". */
335 proto_item_append_text(ti, ": Port Name (\"%s\")",
336 tvb_format_text(tvb, offset+2, p_len));
341 proto_item_append_text(ti, ": unknown");
344 offset = dissect_param_tuple(tvb, p_tree, offset);
355 * Dissect IrCOMM IAS "IrDA:TinyTP:LsapSel" attribute
357 static gboolean dissect_ircomm_ttp_lsap(tvbuff_t* tvb, unsigned offset, packet_info* pinfo,
358 proto_tree* tree, unsigned list_index _U_, guint8 attr_type)
363 if ((dlsap = check_iap_lsap_result(tvb, tree, offset, "IrDA:TinyTP:LsapSel", attr_type)) == 0)
366 add_lmp_conversation(pinfo, dlsap, TRUE, dissect_cooked_ircomm);
373 * Dissect IrCOMM/IrLPT IAS "IrDA:IrLMP:LsapSel" attribute
375 static gboolean dissect_ircomm_lmp_lsap(tvbuff_t* tvb, unsigned offset, packet_info* pinfo,
376 proto_tree* tree, unsigned list_index _U_, guint8 attr_type)
381 if ((dlsap = check_iap_lsap_result(tvb, tree, offset, "IrDA:IrLMP:LsapSel", attr_type)) == 0)
384 add_lmp_conversation(pinfo, dlsap, FALSE, dissect_raw_ircomm);
391 * Register the IrCOMM protocol
393 void proto_register_ircomm(void)
397 /* Setup list of header fields */
398 static hf_register_info hf_ircomm[] = {
400 { "IrCOMM Parameter", "ircomm.parameter",
401 FT_NONE, BASE_NONE, NULL, 0,
404 { "Parameter Identifier", "ircomm.pi",
405 FT_UINT8, BASE_HEX, NULL, 0,
408 { "Parameter Length", "ircomm.pl",
409 FT_UINT8, BASE_HEX, NULL, 0,
412 { "Parameter Value", "ircomm.pv",
413 FT_BYTES, BASE_HEX, NULL, 0,
416 { "Control Channel", "ircomm.control",
417 FT_NONE, BASE_NONE, NULL, 0,
420 { "Clen", "ircomm.control.len",
421 FT_UINT8, BASE_DEC, NULL, 0,
425 /* Setup protocol subtree arrays */
426 static gint* ett[] = {
431 static gint* ett_p[MAX_IAP_ENTRIES * MAX_PARAMETERS];
434 /* Register protocol names and descriptions */
435 proto_ircomm = proto_register_protocol("IrCOMM Protocol", "IrCOMM", "ircomm");
437 /* Required function calls to register the header fields */
438 proto_register_field_array(proto_ircomm, hf_ircomm, array_length(hf_ircomm));
440 /* Register subtrees */
441 proto_register_subtree_array(ett, array_length(ett));
442 for (i = 0; i < MAX_IAP_ENTRIES * MAX_PARAMETERS; i++)
445 ett_p[i] = &ett_param[i];
447 proto_register_subtree_array(ett_p, MAX_IAP_ENTRIES * MAX_PARAMETERS);