1 /* packet-usb-printer.c
3 * Copyright 2020, Martin Kaiser <martin@kaiser.cx>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
15 * USB printer class specification
16 * https://www.usb.org/sites/default/files/usbprint11a021811.pdf
18 * IEEE 1284 (parallel peripheral interface for personal computers)
19 * http://kazus.ru/nuke/modules/Downloads/pub/148/0/IEEE%201284-2000.pdf
23 #include <epan/packet.h>
24 #include <epan/proto.h>
25 #include "packet-usb.h"
26 #include <epan/value_string.h>
28 static dissector_handle_t usb_printer_ctl_handle
;
30 static int proto_usb_printer
;
32 static int hf_usb_printer_req
;
33 static int hf_usb_printer_cfg_idx
;
34 static int hf_usb_printer_intf
;
35 static int hf_usb_printer_alt_set
;
36 static int hf_usb_printer_max_len
;
37 static int hf_usb_printer_dev_id_len
;
38 static int hf_usb_printer_dev_id
;
40 static int ett_usb_printer
;
42 void proto_register_usb_printer(void);
43 void proto_reg_handoff_usb_printer(void);
45 #define REQ_GET_DEV_ID 0
46 #define REQ_GET_PORT_STAT 1
47 #define REQ_GET_SOFT_RST 2
49 static const value_string usb_printer_req
[] = {
50 { REQ_GET_DEV_ID
, "GET_DEVICE_ID" },
51 { REQ_GET_PORT_STAT
, "GET_PORT_STATUS" },
52 { REQ_GET_SOFT_RST
, "SOFT_RESET" },
56 static int dissect_usb_printer_ctl(
57 tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
59 bool is_request
= (pinfo
->srcport
== NO_ENDPOINT
);
60 urb_info_t
*urb
= (urb_info_t
*)data
;
61 usb_trans_info_t
*usb_trans_info
;
69 usb_trans_info
= urb
->usb_trans_info
;
73 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "USBPRINTER");
74 col_set_str(pinfo
->cinfo
, COL_INFO
,
75 val_to_str_const(usb_trans_info
->setup
.request
,
76 usb_printer_req
, "Invalid"));
79 col_append_str(pinfo
->cinfo
, COL_INFO
, " request");
81 bReq
= tvb_get_uint8(tvb
, offset
);
82 proto_tree_add_item(tree
, hf_usb_printer_req
,
83 tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
86 if (bReq
== REQ_GET_DEV_ID
) {
87 /* Generally, fields in USB messages are little endian. */
88 proto_tree_add_item(tree
, hf_usb_printer_cfg_idx
,
89 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
91 proto_tree_add_item(tree
, hf_usb_printer_intf
,
92 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
93 proto_tree_add_item(tree
, hf_usb_printer_alt_set
,
94 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
96 proto_tree_add_item(tree
, hf_usb_printer_max_len
,
97 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
102 col_append_str(pinfo
->cinfo
, COL_INFO
, " response");
104 if (usb_trans_info
->setup
.request
== REQ_GET_DEV_ID
) {
106 * A printer's Device ID is defined in IEEE 1284, section 7.6.
107 * It starts with a 16-bit length field in big endian encoding.
108 * The length field includes the two bytes for itself. Therefore,
109 * we can't use an FT_UINT_STRING for the entire Device ID.
110 * The actual Device ID string consists of ASCII characters.
112 proto_tree_add_item_ret_uint(tree
, hf_usb_printer_dev_id_len
,
113 tvb
, offset
, 2, ENC_BIG_ENDIAN
, &dev_id_len
);
115 if (dev_id_len
> 2) {
116 proto_tree_add_item(tree
, hf_usb_printer_dev_id
,
117 tvb
, offset
, dev_id_len
-2, ENC_ASCII
);
118 offset
+= dev_id_len
-2;
120 /* XXX - expert info for invalid dev_id_len */
127 void proto_register_usb_printer(void)
129 static hf_register_info hf
[] = {
130 { &hf_usb_printer_req
,
131 { "bRequest", "usbprinter.bRequest", FT_UINT8
, BASE_HEX
,
132 VALS(usb_printer_req
), 0x0, NULL
, HFILL
}
134 { &hf_usb_printer_cfg_idx
,
135 { "Config index", "usbprinter.config_index", FT_UINT16
, BASE_HEX
,
136 NULL
, 0x0, NULL
, HFILL
}
138 { &hf_usb_printer_intf
,
139 { "Interface", "usbprinter.interface", FT_UINT16
, BASE_HEX
,
140 NULL
, 0xFF00, NULL
, HFILL
}
142 { &hf_usb_printer_alt_set
,
143 { "Alternate setting", "usbprinter.alt_set", FT_UINT16
, BASE_HEX
,
144 NULL
, 0x00FF, NULL
, HFILL
}
146 { &hf_usb_printer_max_len
,
147 { "Maximum length", "usbprinter.max_len", FT_UINT16
, BASE_HEX
,
148 NULL
, 0, NULL
, HFILL
}
150 { &hf_usb_printer_dev_id_len
,
151 { "Device ID length", "usbprinter.device_id_len", FT_UINT16
,
152 BASE_HEX
, NULL
, 0, NULL
, HFILL
}
154 { &hf_usb_printer_dev_id
,
155 { "Device ID", "usbprinter.device_id", FT_STRING
, BASE_NONE
,
156 NULL
, 0, NULL
, HFILL
}
160 static int *ett
[] = {
164 proto_usb_printer
= proto_register_protocol("USB Printer", "USBPRINTER", "usbprinter");
165 proto_register_field_array(proto_usb_printer
, hf
, array_length(hf
));
166 proto_register_subtree_array(ett
, array_length(ett
));
167 usb_printer_ctl_handle
= register_dissector("usbprinter", dissect_usb_printer_ctl
, proto_usb_printer
);
171 proto_reg_handoff_usb_printer(void)
173 dissector_add_uint("usb.control", IF_CLASS_PRINTER
, usb_printer_ctl_handle
);
177 * Editor modelines - https://www.wireshark.org/tools/modelines.html
182 * indent-tabs-mode: nil
185 * ex: set shiftwidth=4 tabstop=8 expandtab:
186 * :indentSize=4:tabSize=8:noTabs=true: