2 * Routines for I2C captures (using libpcap extensions)
4 * Pigeon Point Systems <www.pigeonpoint.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/exceptions.h>
33 #include <epan/prefs.h>
35 #include "packet-i2c.h"
36 #include "packet-hdcp.h"
38 static int proto_i2c
= -1;
40 static int hf_i2c_bus
= -1;
41 static int hf_i2c_event
= -1;
42 static int hf_i2c_flags
= -1;
43 static int hf_i2c_addr
= -1;
45 static gint ett_i2c
= -1;
55 typedef gboolean (*sub_checkfunc_t
)(packet_info
*);
57 static dissector_handle_t sub_handles
[SUB_MAX
];
58 static gint sub_selected
= SUB_IPMB
;
60 /* I2C packet flags. */
61 #define I2C_FLAG_RD 0x00000001
62 #define I2C_FLAG_TEN 0x00000010
63 #define I2C_FLAG_REV_DIR_ADDR 0x00002000
64 #define I2C_FLAG_NOSTART 0x00004000
67 #define I2C_EVENT_PROM_ON (1 << 0) /* Promiscuous mode: on */
68 #define I2C_EVENT_PROM_OFF (1 << 1) /* Promiscuous mode: off */
69 #define I2C_EVENT_ONLINE_ON (1 << 2) /* Online state: on */
70 #define I2C_EVENT_ONLINE_OFF (1 << 3) /* Online state: off */
71 #define I2C_EVENT_ATTACHED_ON (1 << 4) /* Attached state: on */
72 #define I2C_EVENT_ATTACHED_OFF (1 << 5) /* Attached state: off */
73 #define I2C_EVENT_PROM_OVFL_ON (1 << 6) /* Prom. queue overflow: on */
74 #define I2C_EVENT_PROM_OVFL_OFF (1 << 7) /* Prom. queue overflow: off */
75 #define I2C_EVENT_OVFL_ON (1 << 8) /* Queue overflow: on */
76 #define I2C_EVENT_OVFL_OFF (1 << 9) /* Queue overflow: off */
79 #define I2C_EVENT_ERR_DATA_LO (1 << 16) /* Unable to drive data LO */
80 #define I2C_EVENT_ERR_DATA_HI (1 << 17) /* Unable to drive data HI */
81 #define I2C_EVENT_ERR_CLOCK_LO (1 << 18) /* Unable to drive clock LO */
82 #define I2C_EVENT_ERR_CLOCK_HI (1 << 19) /* Unable to drive clock HI */
83 #define I2C_EVENT_ERR_CLOCK_TO (1 << 20) /* Clock low timeout */
84 #define I2C_EVENT_ERR_PHYS (1 << 21) /* The I2C bus controller
86 disconnected from the bus */
87 #define I2C_EVENT_ERR_FAIL (1 << 22) /* Undiagnosed failure */
90 capture_i2c(union wtap_pseudo_header
*pseudo_header
, packet_counts
*ld
)
92 if (pseudo_header
->i2c
.is_event
) {
100 i2c_get_event_desc(int event
)
104 switch (event
& 0x0000ffff) {
105 case I2C_EVENT_PROM_ON
:
106 desc
= "Promiscuous mode is enabled";
108 case I2C_EVENT_PROM_OFF
:
109 desc
= "Promiscuous mode is disabled";
111 case I2C_EVENT_ONLINE_ON
:
112 desc
= "The I2C controller is operational";
114 case I2C_EVENT_ONLINE_OFF
:
115 desc
= "The I2C controller is non-operational";
117 case I2C_EVENT_ATTACHED_ON
:
118 desc
= "The I2C controller is attached to an I2C bus";
120 case I2C_EVENT_ATTACHED_OFF
:
121 desc
= "The I2C controller is detached from an I2C bus";
122 if (event
& I2C_EVENT_ERR_DATA_LO
) {
123 desc
= "The I2C controller is detached from an I2C bus: "
124 "unable to drive data LO";
125 } else if (event
& I2C_EVENT_ERR_DATA_HI
) {
126 desc
= "The I2C controller is detached from an I2C bus: "
127 "unable to drive data HI";
128 } else if (event
& I2C_EVENT_ERR_CLOCK_LO
) {
129 desc
= "The I2C controller is detached from an I2C bus: "
130 "unable to drive clock LO";
131 } else if (event
& I2C_EVENT_ERR_CLOCK_HI
) {
132 desc
= "The I2C controller is detached from an I2C bus: "
133 "unable to drive clock HI";
134 } else if (event
& I2C_EVENT_ERR_CLOCK_TO
) {
135 desc
= "The I2C controller is detached from an I2C bus: "
137 } else if (event
& I2C_EVENT_ERR_PHYS
) {
138 desc
= "The I2C controller is detached from an I2C bus: "
139 "the I2C bus controller has been physically "
140 "disconnected from the bus";
141 } else if (event
& I2C_EVENT_ERR_FAIL
) {
142 desc
= "The I2C controller is detached from an I2C bus: "
143 "undiagnosed failure";
146 case I2C_EVENT_PROM_OVFL_ON
:
147 desc
= "The incoming promiscuous data buffer has been overrun; "
150 case I2C_EVENT_PROM_OVFL_OFF
:
151 desc
= "The incoming promiscuous data buffer is available";
153 case I2C_EVENT_OVFL_ON
:
154 desc
= "The incoming I2C data buffer has been overrun; "
157 case I2C_EVENT_OVFL_OFF
:
158 desc
= "The incoming I2C data buffer is available";
161 desc
= "<unknown state event>";
169 sub_check_ipmb(packet_info
*pinfo
)
171 if (pinfo
->pseudo_header
->i2c
.flags
& I2C_FLAG_RD
) {
172 /* Master-receive transactions are not possible on IPMB */
179 static sub_checkfunc_t sub_check
[SUB_MAX
] = {
181 sub_check_ipmb
, /* IPMI */
182 sub_check_hdcp
/* HDCP */
186 dissect_i2c(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
189 proto_tree
*i2c_tree
= NULL
;
190 int is_event
, bus
, flags
, addr
, len
;
192 is_event
= pinfo
->pseudo_header
->i2c
.is_event
;
193 flags
= pinfo
->pseudo_header
->i2c
.flags
;
194 bus
= pinfo
->pseudo_header
->i2c
.bus
;
195 len
= tvb_length(tvb
);
200 THROW(ReportedBoundsError
);
202 /* Report 7-bit hardware address */
203 addr
= tvb_get_guint8(tvb
, 0) >> 1;
206 pinfo
->ptype
= PT_I2C
;
209 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "I2C Event");
211 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
, "I2C %s",
212 (flags
& I2C_FLAG_RD
) ? "Read" : "Write");
214 col_add_fstr(pinfo
->cinfo
, COL_DEF_SRC
, "I2C-%d", bus
);
217 col_add_fstr(pinfo
->cinfo
, COL_DEF_DST
, "----");
219 col_add_fstr(pinfo
->cinfo
, COL_DEF_DST
, "0x%02x", addr
);
222 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s",
223 i2c_get_event_desc(flags
));
225 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "I2C %s, %d bytes",
226 (flags
& I2C_FLAG_RD
) ? "Read" : "Write", len
);
229 ti
= proto_tree_add_protocol_format(tree
, proto_i2c
, tvb
, 0, -1,
230 "Inter-Integrated Circuit (%s)",
231 is_event
? "Event" : "Data");
233 i2c_tree
= proto_item_add_subtree(ti
, ett_i2c
);
234 proto_tree_add_uint_format(i2c_tree
, hf_i2c_bus
, tvb
, 0, 0, bus
,
238 proto_tree_add_uint_format_value(i2c_tree
, hf_i2c_event
, tvb
, 0, 0,
239 flags
, "%s (0x%08x)",
240 i2c_get_event_desc(flags
), flags
);
242 proto_tree_add_uint_format_value(i2c_tree
, hf_i2c_addr
, tvb
, 0, 1,
243 addr
, "0x%02x%s", addr
, addr
? "" : " (General Call)");
244 proto_tree_add_uint_format_value(i2c_tree
, hf_i2c_flags
, tvb
, 0, 0,
245 flags
, "0x%08x", flags
);
250 if (sub_check
[sub_selected
] && sub_check
[sub_selected
](pinfo
)) {
251 call_dissector(sub_handles
[sub_selected
], tvb
, pinfo
, tree
);
253 call_dissector(sub_handles
[SUB_DATA
], tvb
, pinfo
, tree
);
259 proto_register_i2c(void)
261 static hf_register_info hf
[] = {
262 { &hf_i2c_bus
, { "Bus ID", "i2c.bus", FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
263 { &hf_i2c_addr
, { "Target address", "i2c.addr", FT_UINT8
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
264 { &hf_i2c_event
, { "Event", "i2c.event", FT_UINT32
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
265 { &hf_i2c_flags
, { "Flags", "i2c.flags", FT_UINT32
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
267 static gint
*ett
[] = {
270 static const enum_val_t sub_enum_vals
[] = {
271 { "none", "None (raw I2C)", SUB_DATA
},
272 { "ipmb", "IPMB", SUB_IPMB
},
273 { "hdcp", "HDCP", SUB_HDCP
},
278 proto_i2c
= proto_register_protocol("Inter-Integrated Circuit", "I2C", "i2c");
279 proto_register_field_array(proto_i2c
, hf
, array_length(hf
));
280 proto_register_subtree_array(ett
, array_length(ett
));
282 m
= prefs_register_protocol(proto_i2c
, NULL
);
283 prefs_register_enum_preference(m
, "type", "Bus/Data type",
284 "How the I2C messages are interpreted",
285 &sub_selected
, sub_enum_vals
, FALSE
);
289 proto_reg_handoff_i2c(void)
291 dissector_handle_t i2c_handle
;
293 sub_handles
[SUB_DATA
] = find_dissector("data");
294 sub_handles
[SUB_IPMB
] = find_dissector("ipmi");
295 sub_handles
[SUB_HDCP
] = find_dissector("hdcp");
296 i2c_handle
= create_dissector_handle(dissect_i2c
, proto_i2c
);
297 dissector_add_uint("wtap_encap", WTAP_ENCAP_I2C
, i2c_handle
);