Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-usb-ccid.c
blob06058bbc355bbd73cc4df9be516426aacb075fec
1 /* packet-usb-ccid.c
2 * Dissector for the Integrated Circuit Card Interface Device Class
4 * References:
5 * http://www.usb.org/developers/devclass_docs/DWG_Smart-Card_CCID_Rev110.pdf
7 * Copyright 2011, Tyson Key <tyson.key@gmail.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include "config.h"
18 #include <epan/decode_as.h>
19 #include <epan/packet.h>
20 #include <epan/prefs.h>
21 #include <epan/tfs.h>
22 #include <epan/unit_strings.h>
24 #include <wsutil/array.h>
25 #include "packet-usb.h"
27 static int proto_ccid;
29 static dissector_table_t subdissector_table;
31 static int hf_ccid_bMessageType;
32 static int hf_ccid_dwLength;
33 static int hf_ccid_bSlot;
34 static int hf_ccid_bSeq;
35 static int hf_ccid_bStatus;
36 static int hf_ccid_bStatus_bmIccStatus;
37 static int hf_ccid_bStatus_bmCommandStatus;
38 static int hf_ccid_bError;
39 static int hf_ccid_bRFU;
40 static int hf_ccid_abRFU;
41 static int hf_ccid_bChainParameter;
42 static int hf_ccid_bPowerSelect;
43 static int hf_ccid_bClockStatus;
44 static int hf_ccid_bProtocolNum;
45 static int hf_ccid_bBWI;
46 static int hf_ccid_wLevelParameter;
47 static int hf_ccid_bcdCCID;
48 static int hf_ccid_bMaxSlotIndex;
49 static int hf_ccid_bVoltageSupport;
50 static int hf_ccid_bVoltageSupport18;
51 static int hf_ccid_bVoltageSupport30;
52 static int hf_ccid_bVoltageSupport50;
53 static int hf_ccid_dwProtocols;
54 static int hf_ccid_dwProtocols_t0;
55 static int hf_ccid_dwProtocols_t1;
56 static int hf_ccid_dwDefaultClock;
57 static int hf_ccid_dwMaximumClock;
58 static int hf_ccid_bNumClockSupported;
59 static int hf_ccid_dwDataRate;
60 static int hf_ccid_dwMaxDataRate;
61 static int hf_ccid_bNumDataRatesSupported;
62 static int hf_ccid_dwMaxIFSD;
63 static int hf_ccid_dwSynchProtocols;
64 static int hf_ccid_dwMechanical;
65 static int hf_ccid_dwFeatures;
66 static int hf_ccid_dwFeatures_autoParam;
67 static int hf_ccid_dwFeatures_autoIccActivation;
68 static int hf_ccid_dwFeatures_autoIccVoltSelect;
69 static int hf_ccid_dwFeatures_autoIccClk;
70 static int hf_ccid_dwFeatures_autoBaudRate;
71 static int hf_ccid_dwFeatures_autoParamNegotiation;
72 static int hf_ccid_dwFeatures_autoPPS;
73 static int hf_ccid_dwFeatures_stopIccClk;
74 static int hf_ccid_dwFeatures_nadValNot0accept;
75 static int hf_ccid_dwFeatures_autoIfsd;
76 static int hf_ccid_dwFeatures_levelExchangeTDPU;
77 static int hf_ccid_dwFeatures_levelExchangeShortAPDU;
78 static int hf_ccid_dwFeatures_levelExchangeShortExtendedAPDU;
79 static int hf_ccid_dwFeatures_UsbWakeUp;
80 static int hf_ccid_dwMaxCCIDMessageLength;
81 static int hf_ccid_bClassGetResponse;
82 static int hf_ccid_bClassEnvelope;
83 static int hf_ccid_wLcdLayout;
84 static int hf_ccid_wLcdLayout_lines;
85 static int hf_ccid_wLcdLayout_chars;
86 static int hf_ccid_bPINSupport;
87 static int hf_ccid_bPINSupport_modify;
88 static int hf_ccid_bPINSupport_vrfy;
89 static int hf_ccid_bMaxCCIDBusySlots;
90 static int hf_ccid_Reserved;
91 static int hf_ccid_bmSlotICCState;
92 static int hf_ccid_bmSlotICCState_slot0Current;
93 static int hf_ccid_bmSlotICCState_slot0Changed;
94 static int hf_ccid_bmSlotICCState_slot1Current;
95 static int hf_ccid_bmSlotICCState_slot1Changed;
96 static int hf_ccid_bmSlotICCState_slot2Current;
97 static int hf_ccid_bmSlotICCState_slot2Changed;
98 static int hf_ccid_bmSlotICCState_slot3Current;
99 static int hf_ccid_bmSlotICCState_slot3Changed;
100 static int hf_ccid_bmSlotICCState_slot4Current;
101 static int hf_ccid_bmSlotICCState_slot4Changed;
102 static int hf_ccid_bmSlotICCState_slot5Current;
103 static int hf_ccid_bmSlotICCState_slot5Changed;
104 static int hf_ccid_bmSlotICCState_slot6Current;
105 static int hf_ccid_bmSlotICCState_slot6Changed;
106 static int hf_ccid_bmSlotICCState_slot7Current;
107 static int hf_ccid_bmSlotICCState_slot7Changed;
108 static int hf_ccid_bHardwareErrorCode;
109 static int hf_ccid_bmFindexDindex;
110 static int hf_ccid_bmTCCKST0;
111 static int hf_ccid_bmTCCKST1;
112 static int hf_ccid_bGuardTimeT0;
113 static int hf_ccid_bGuardTimeT1;
114 static int hf_ccid_bWaitingIntegerT0;
115 static int hf_ccid_bmWaitingIntegersT1;
116 static int hf_ccid_bClockStop;
117 static int hf_ccid_bIFSC;
118 static int hf_ccid_bNadValue;
120 static dissector_handle_t usb_ccid_handle;
121 static dissector_handle_t usb_ccid_descr_handle;
124 static int * const bVoltageLevel_fields[] = {
125 &hf_ccid_bVoltageSupport18,
126 &hf_ccid_bVoltageSupport30,
127 &hf_ccid_bVoltageSupport50,
128 NULL
131 static int * const dwProtocols_fields[] = {
132 &hf_ccid_dwProtocols_t0,
133 &hf_ccid_dwProtocols_t1,
134 NULL
137 static int * const bFeatures_fields[] = {
138 /* XXX - add the missing components */
139 &hf_ccid_dwFeatures_autoParam,
140 &hf_ccid_dwFeatures_autoIccActivation,
141 &hf_ccid_dwFeatures_autoIccVoltSelect,
142 &hf_ccid_dwFeatures_autoIccClk,
143 &hf_ccid_dwFeatures_autoBaudRate,
144 &hf_ccid_dwFeatures_autoParamNegotiation,
145 &hf_ccid_dwFeatures_autoPPS,
146 &hf_ccid_dwFeatures_stopIccClk,
147 &hf_ccid_dwFeatures_nadValNot0accept,
148 &hf_ccid_dwFeatures_autoIfsd,
149 &hf_ccid_dwFeatures_levelExchangeTDPU,
150 &hf_ccid_dwFeatures_levelExchangeShortAPDU,
151 &hf_ccid_dwFeatures_levelExchangeShortExtendedAPDU,
152 &hf_ccid_dwFeatures_UsbWakeUp,
153 NULL
156 static int * const bPINSupport_fields[] = {
157 &hf_ccid_bPINSupport_modify,
158 &hf_ccid_bPINSupport_vrfy,
159 NULL
162 static int * const bmSlotICCStateb0_fields[] = {
163 &hf_ccid_bmSlotICCState_slot0Current,
164 &hf_ccid_bmSlotICCState_slot0Changed,
165 &hf_ccid_bmSlotICCState_slot1Current,
166 &hf_ccid_bmSlotICCState_slot1Changed,
167 &hf_ccid_bmSlotICCState_slot2Current,
168 &hf_ccid_bmSlotICCState_slot2Changed,
169 &hf_ccid_bmSlotICCState_slot3Current,
170 &hf_ccid_bmSlotICCState_slot3Changed,
171 NULL
174 static int * const bmSlotICCStateb1_fields[] = {
175 &hf_ccid_bmSlotICCState_slot4Current,
176 &hf_ccid_bmSlotICCState_slot4Changed,
177 &hf_ccid_bmSlotICCState_slot5Current,
178 &hf_ccid_bmSlotICCState_slot5Changed,
179 &hf_ccid_bmSlotICCState_slot6Current,
180 &hf_ccid_bmSlotICCState_slot6Changed,
181 &hf_ccid_bmSlotICCState_slot7Current,
182 &hf_ccid_bmSlotICCState_slot7Changed,
183 NULL
186 static int * const bStatus_fields[] = {
187 &hf_ccid_bStatus_bmIccStatus,
188 &hf_ccid_bStatus_bmCommandStatus,
189 NULL
192 /* smart card descriptor, as defined in section 5.1
193 of the USB CCID specification */
194 #define USB_DESC_TYPE_SMARTCARD 0x21
196 /* Standardised Bulk Out message types */
197 #define PC_RDR_SET_PARAMS 0x61
198 #define PC_RDR_ICC_ON 0x62
199 #define PC_RDR_ICC_OFF 0x63
200 #define PC_RDR_GET_SLOT_STATUS 0x65
201 #define PC_RDR_SECURE 0x69
202 #define PC_RDR_T0APDU 0x6A
203 #define PC_RDR_ESCAPE 0x6B
204 #define PC_RDR_GET_PARAMS 0x6C
205 #define PC_RDR_RESET_PARAMS 0x6D
206 #define PC_RDR_ICC_CLOCK 0x6E
207 #define PC_RDR_XFR_BLOCK 0x6F
208 #define PC_RDR_MECH 0x71
209 #define PC_RDR_ABORT 0x72
210 #define PC_RDR_DATA_CLOCK 0x73
212 /* Standardised Bulk In message types */
213 #define RDR_PC_DATA_BLOCK 0x80
214 #define RDR_PC_SLOT_STATUS 0x81
215 #define RDR_PC_PARAMS 0x82
216 #define RDR_PC_ESCAPE 0x83
217 #define RDR_PC_DATA_CLOCK 0x84
219 /* Standardised Interrupt IN message types */
220 #define RDR_PC_NOTIF_SLOT_CHNG 0x50
221 #define RDR_PC_HWERROR 0x51
223 void proto_register_ccid(void);
224 void proto_reg_handoff_ccid(void);
226 static const value_string ccid_descriptor_type_vals[] = {
227 {USB_DESC_TYPE_SMARTCARD, "smart card"},
228 {0,NULL}
230 static value_string_ext ccid_descriptor_type_vals_ext =
231 VALUE_STRING_EXT_INIT(ccid_descriptor_type_vals);
233 static const value_string ccid_opcode_vals[] = {
234 /* Standardised Bulk Out message types */
235 {PC_RDR_SET_PARAMS , "PC_to_RDR_SetParameters"},
236 {PC_RDR_ICC_ON , "PC_to_RDR_IccPowerOn"},
237 {PC_RDR_ICC_OFF , "PC_to_RDR_IccPowerOff"},
238 {PC_RDR_GET_SLOT_STATUS , "PC_to_RDR_GetSlotStatus"},
239 {PC_RDR_SECURE , "PC_to_RDR_Secure"},
240 {PC_RDR_T0APDU , "PC_to_RDR_T0APDU"},
241 {PC_RDR_ESCAPE , "PC_to_RDR_Escape"},
242 {PC_RDR_GET_PARAMS , "PC_to_RDR_GetParameters"},
243 {PC_RDR_RESET_PARAMS , "PC_to_RDR_ResetParameters"},
244 {PC_RDR_ICC_CLOCK , "PC_to_RDR_IccClock"},
245 {PC_RDR_XFR_BLOCK , "PC_to_RDR_XfrBlock"},
246 {PC_RDR_MECH , "PC_to_RDR_Mechanical"},
247 {PC_RDR_ABORT , "PC_to_RDR_Abort"},
248 {PC_RDR_DATA_CLOCK , "PC_to_RDR_SetDataRateAndClockFrequency"},
250 /* Standardised Bulk In message types */
251 {RDR_PC_DATA_BLOCK , "RDR_to_PC_DataBlock"},
252 {RDR_PC_SLOT_STATUS , "RDR_to_PC_SlotStatus"},
253 {RDR_PC_PARAMS , "RDR_to_PC_Parameters"},
254 {RDR_PC_ESCAPE , "RDR_to_PC_Escape"},
255 {RDR_PC_DATA_CLOCK , "RDR_to_PC_DataRateAndClockFrequency"},
257 /* Standardised Interrupt IN message types */
258 {RDR_PC_NOTIF_SLOT_CHNG , "RDR_to_PC_NotifySlotChange"},
259 {RDR_PC_HWERROR , "RDR_to_PC_HardwareError"},
261 /* End of message types */
262 {0x00, NULL}
265 static const value_string ccid_messagetypes_vals[] = {
266 /* Standardised Bulk Out message types */
267 {PC_RDR_SET_PARAMS , "PC to Reader: Set Parameters"},
268 {PC_RDR_ICC_ON , "PC to Reader: ICC Power On"},
269 {PC_RDR_ICC_OFF , "PC to Reader: ICC Power Off"},
270 {PC_RDR_GET_SLOT_STATUS , "PC to Reader: Get Slot Status"},
271 {PC_RDR_SECURE , "PC to Reader: Secure"},
272 {PC_RDR_T0APDU , "PC to Reader: T=0 APDU"},
273 {PC_RDR_ESCAPE , "PC to Reader: Escape"},
274 {PC_RDR_GET_PARAMS , "PC to Reader: Get Parameters"},
275 {PC_RDR_RESET_PARAMS , "PC to Reader: Reset Parameters"},
276 {PC_RDR_ICC_CLOCK , "PC to Reader: ICC Clock"},
277 {PC_RDR_XFR_BLOCK , "PC to Reader: Transfer Block"},
278 {PC_RDR_MECH , "PC to Reader: Mechanical"},
279 {PC_RDR_ABORT , "PC to Reader: Abort"},
280 {PC_RDR_DATA_CLOCK , "PC to Reader: Set Data Rate and Clock Frequency"},
282 /* Standardised Bulk In message types */
283 {RDR_PC_DATA_BLOCK , "Reader to PC: Data Block"},
284 {RDR_PC_SLOT_STATUS , "Reader to PC: Slot Status"},
285 {RDR_PC_PARAMS , "Reader to PC: Parameters"},
286 {RDR_PC_ESCAPE , "Reader to PC: Escape"},
287 {RDR_PC_DATA_CLOCK , "Reader to PC: Data Rate and Clock Frequency"},
289 /* Standardised Interrupt IN message types */
290 {RDR_PC_NOTIF_SLOT_CHNG , "Reader to PC: Notify Slot Change"},
291 {RDR_PC_HWERROR , "Reader to PC: Hardware Error"},
293 /* End of message types */
294 {0x00, NULL}
297 static const value_string ccid_voltage_levels_vals[] = {
298 /* Standardised voltage levels */
299 {0x00, "Automatic Voltage Selection"},
300 {0x01, "5.0 volts"},
301 {0x02, "3.0 volts"},
302 {0x03, "1.8 volts"},
304 /* End of voltage levels */
305 {0x00, NULL}
308 static const value_string ccid_clock_states_vals[] = {
309 /* Standardised clock states */
310 {0x00, "Clock running"},
311 {0x01, "Clock stopped in state L"},
312 {0x02, "Clock stopped in state H"},
313 {0x03, "Clock stopped in an unknown state"},
315 /* End of clock states */
316 {0x00, NULL}
319 static const value_string ccid_proto_structs_vals[] = {
320 /* Standardised clock states */
321 {0x00, "Structure for protocol T=0"},
322 {0x01, "Structure for protocol T=1"},
324 /* Marked as RFU, but added for completeness: */
325 {0x80, "Structure for 2-wire protocol"},
326 {0x81, "Structure for 3-wire protocol"},
327 {0x82, "Structure for I2C protocol"},
329 /* End of protocol structures */
330 {0x00, NULL}
333 static const value_string ccid_status_icc_status_vals[] = {
334 /* Standardised icc status */
335 { 0x00, "An ICC is present and active" },
336 { 0x01, "An ICC is present and inactive" },
337 { 0x02, "No ICC is present" },
338 { 0x03, "RFU" },
340 /* End of icc status */
341 { 0x00, NULL }
344 static const value_string ccid_status_cmd_status_vals[] = {
345 /* Standardised status values */
346 { 0x00, "Processed without error " },
347 { 0x01, "Failed" },
348 { 0x02, "Time Extension is requested " },
349 { 0x03, "RFU" },
351 /* End of status values */
352 { 0x00, NULL }
355 /* Subtree handles: set by register_subtree_array */
356 static int ett_ccid;
357 static int ett_ccid_desc;
358 static int ett_ccid_protocol_data_structure;
359 static int ett_ccid_voltage_level;
360 static int ett_ccid_protocols;
361 static int ett_ccid_features;
362 static int ett_ccid_lcd_layout;
363 static int ett_ccid_pin_support;
364 static int ett_ccid_slot_change;
365 static int ett_ccid_status;
367 static int
368 dissect_usb_ccid_descriptor(tvbuff_t *tvb, packet_info *pinfo _U_,
369 proto_tree *tree, void *data _U_)
371 int offset = 0;
372 uint8_t descriptor_type;
373 uint8_t descriptor_len;
374 proto_item *freq_item;
375 proto_tree *desc_tree;
376 uint8_t num_clock_supp;
377 proto_item *lcd_layout_item;
378 proto_tree *lcd_layout_tree;
380 descriptor_len = tvb_get_uint8(tvb, offset);
381 descriptor_type = tvb_get_uint8(tvb, offset+1);
382 if (descriptor_type!=USB_DESC_TYPE_SMARTCARD)
383 return 0;
385 desc_tree = proto_tree_add_subtree(tree, tvb, offset, descriptor_len,
386 ett_ccid_desc, NULL, "SMART CARD DEVICE CLASS DESCRIPTOR");
388 dissect_usb_descriptor_header(desc_tree, tvb, offset,
389 &ccid_descriptor_type_vals_ext);
390 offset += 2;
392 proto_tree_add_item(desc_tree, hf_ccid_bcdCCID, tvb,
393 offset, 2, ENC_LITTLE_ENDIAN);
394 offset += 2;
396 proto_tree_add_item(desc_tree, hf_ccid_bMaxSlotIndex, tvb,
397 offset, 1, ENC_LITTLE_ENDIAN);
398 offset++;
399 proto_tree_add_bitmask(desc_tree, tvb, offset,
400 hf_ccid_bVoltageSupport, ett_ccid_voltage_level, bVoltageLevel_fields,
401 ENC_LITTLE_ENDIAN);
402 offset++;
404 proto_tree_add_bitmask(desc_tree, tvb, offset,
405 hf_ccid_dwProtocols, ett_ccid_protocols, dwProtocols_fields,
406 ENC_LITTLE_ENDIAN);
407 offset += 4;
409 proto_tree_add_item(desc_tree, hf_ccid_dwDefaultClock, tvb,
410 offset, 4, ENC_LITTLE_ENDIAN);
411 offset += 4;
412 proto_tree_add_item(desc_tree, hf_ccid_dwMaximumClock, tvb,
413 offset, 4, ENC_LITTLE_ENDIAN);
414 offset += 4;
415 num_clock_supp = tvb_get_uint8(tvb, offset);
416 freq_item = proto_tree_add_item(desc_tree, hf_ccid_bNumClockSupported, tvb,
417 offset, 1, ENC_LITTLE_ENDIAN);
418 if (num_clock_supp==0)
419 proto_item_append_text(freq_item, " (only default and maximum)");
420 offset++;
422 proto_tree_add_item(desc_tree, hf_ccid_dwDataRate,
423 tvb, offset, 4, ENC_LITTLE_ENDIAN);
424 offset += 4;
425 proto_tree_add_item(desc_tree, hf_ccid_dwMaxDataRate,
426 tvb, offset, 4, ENC_LITTLE_ENDIAN);
427 offset += 4;
428 proto_tree_add_item(desc_tree, hf_ccid_bNumDataRatesSupported,
429 tvb, offset, 1, ENC_LITTLE_ENDIAN);
430 offset++;
432 proto_tree_add_item(desc_tree, hf_ccid_dwMaxIFSD,
433 tvb, offset, 4, ENC_LITTLE_ENDIAN);
434 offset += 4;
436 proto_tree_add_item(desc_tree, hf_ccid_dwSynchProtocols,
437 tvb, offset, 4, ENC_LITTLE_ENDIAN);
438 offset += 4;
440 proto_tree_add_item(desc_tree, hf_ccid_dwMechanical,
441 tvb, offset, 4, ENC_LITTLE_ENDIAN);
442 offset += 4;
444 proto_tree_add_bitmask(desc_tree, tvb, offset,
445 hf_ccid_dwFeatures, ett_ccid_features, bFeatures_fields,
446 ENC_LITTLE_ENDIAN);
447 offset += 4;
449 proto_tree_add_item(desc_tree, hf_ccid_dwMaxCCIDMessageLength,
450 tvb, offset, 4, ENC_LITTLE_ENDIAN);
451 offset += 4;
453 proto_tree_add_item(desc_tree, hf_ccid_bClassGetResponse,
454 tvb, offset, 1, ENC_LITTLE_ENDIAN);
455 offset++;
456 proto_tree_add_item(desc_tree, hf_ccid_bClassEnvelope,
457 tvb, offset, 1, ENC_LITTLE_ENDIAN);
458 offset++;
460 lcd_layout_item = proto_tree_add_item(desc_tree, hf_ccid_wLcdLayout,
461 tvb, offset, 2, ENC_LITTLE_ENDIAN);
462 lcd_layout_tree = proto_item_add_subtree(
463 lcd_layout_item, ett_ccid_lcd_layout);
464 proto_tree_add_item(lcd_layout_tree, hf_ccid_wLcdLayout_lines,
465 tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
466 proto_tree_add_item(lcd_layout_tree, hf_ccid_wLcdLayout_chars,
467 tvb, offset, 1, ENC_LITTLE_ENDIAN);
468 offset += 2;
470 proto_tree_add_bitmask(desc_tree, tvb, offset,
471 hf_ccid_bPINSupport, ett_ccid_pin_support, bPINSupport_fields,
472 ENC_LITTLE_ENDIAN);
473 offset++;
475 proto_tree_add_item(desc_tree, hf_ccid_bMaxCCIDBusySlots,
476 tvb, offset, 1, ENC_LITTLE_ENDIAN);
477 offset++;
479 return offset;
483 static int
484 dissect_ccid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
486 proto_item *item;
487 proto_tree *ccid_tree;
488 uint8_t cmd;
489 uint32_t payload_len;
490 tvbuff_t *next_tvb;
491 urb_info_t *urb;
492 int len_remaining;
493 uint8_t bProtocolNum;
494 proto_tree *protocol_tree;
496 /* Reject the packet if data is NULL */
497 if (data == NULL)
498 return 0;
499 urb = (urb_info_t *)data;
501 col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBCCID");
502 col_set_str(pinfo->cinfo, COL_INFO, "CCID Packet");
504 /* Start with a top-level item to add everything else to */
505 item = proto_tree_add_item(tree, proto_ccid, tvb, 0, 10, ENC_NA);
506 ccid_tree = proto_item_add_subtree(item, ett_ccid);
508 proto_tree_add_item(ccid_tree, hf_ccid_bMessageType, tvb, 0, 1, ENC_LITTLE_ENDIAN);
509 cmd = tvb_get_uint8(tvb, 0);
511 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", val_to_str_const(cmd, ccid_messagetypes_vals, "Unknown"));
513 switch (cmd) {
515 case PC_RDR_SET_PARAMS:
516 proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
517 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
518 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
519 proto_tree_add_item(ccid_tree, hf_ccid_bProtocolNum, tvb, 7, 1, ENC_LITTLE_ENDIAN);
521 /* Placeholder for abRFU */
522 proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 8, 2, ENC_LITTLE_ENDIAN);
524 payload_len = tvb_get_letohl(tvb, 1);
526 /* abProtocolDataStructure */
527 bProtocolNum = tvb_get_uint8(tvb, 7);
528 switch (bProtocolNum)
530 case 0: /* T=0 */
531 protocol_tree = proto_tree_add_subtree(tree, tvb, 10, payload_len, ett_ccid_protocol_data_structure, NULL, "Protocol Data Structure for Protocol T=0");
532 proto_tree_add_item(protocol_tree, hf_ccid_bmFindexDindex, tvb, 10, 1, ENC_LITTLE_ENDIAN);
533 proto_tree_add_item(protocol_tree, hf_ccid_bmTCCKST0, tvb, 11, 1, ENC_LITTLE_ENDIAN);
534 proto_tree_add_item(protocol_tree, hf_ccid_bGuardTimeT0, tvb, 12, 1, ENC_LITTLE_ENDIAN);
535 proto_tree_add_item(protocol_tree, hf_ccid_bWaitingIntegerT0, tvb, 13, 1, ENC_LITTLE_ENDIAN);
536 proto_tree_add_item(protocol_tree, hf_ccid_bClockStop, tvb, 14, 1, ENC_LITTLE_ENDIAN);
537 break;
539 case 1: /* T=1 */
540 protocol_tree = proto_tree_add_subtree(tree, tvb, 10, payload_len, ett_ccid_protocol_data_structure, NULL, "Protocol Data Structure for Protocol T=1");
541 proto_tree_add_item(protocol_tree, hf_ccid_bmFindexDindex, tvb, 10, 1, ENC_LITTLE_ENDIAN);
542 proto_tree_add_item(protocol_tree, hf_ccid_bmTCCKST1, tvb, 11, 1, ENC_LITTLE_ENDIAN);
543 proto_tree_add_item(protocol_tree, hf_ccid_bGuardTimeT1, tvb, 12, 1, ENC_LITTLE_ENDIAN);
544 proto_tree_add_item(protocol_tree, hf_ccid_bmWaitingIntegersT1, tvb, 13, 1, ENC_LITTLE_ENDIAN);
545 proto_tree_add_item(protocol_tree, hf_ccid_bClockStop, tvb, 14, 1, ENC_LITTLE_ENDIAN);
546 proto_tree_add_item(protocol_tree, hf_ccid_bIFSC, tvb, 15, 1, ENC_LITTLE_ENDIAN);
547 proto_tree_add_item(protocol_tree, hf_ccid_bNadValue, tvb, 16, 1, ENC_LITTLE_ENDIAN);
548 break;
550 default:
551 next_tvb = tvb_new_subset_remaining(tvb, 10);
552 call_data_dissector(next_tvb, pinfo, tree);
554 break;
556 case PC_RDR_ICC_ON:
557 proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
558 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
559 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
560 proto_tree_add_item(ccid_tree, hf_ccid_bPowerSelect, tvb, 7, 1, ENC_LITTLE_ENDIAN);
562 /* Placeholder for abRFU */
563 proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 8, 2, ENC_LITTLE_ENDIAN);
564 break;
566 case PC_RDR_ICC_OFF:
567 proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
568 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
569 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
571 /* Placeholder for abRFU */
572 proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 7, 3, ENC_LITTLE_ENDIAN);
573 break;
575 case PC_RDR_GET_SLOT_STATUS:
576 proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
577 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
578 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
580 /* Placeholder for abRFU */
581 proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 7, 3, ENC_LITTLE_ENDIAN);
582 break;
584 case PC_RDR_GET_PARAMS:
585 proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
586 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
587 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
589 /* Placeholder for abRFU */
590 proto_tree_add_item(ccid_tree, hf_ccid_Reserved, tvb, 7, 3, ENC_LITTLE_ENDIAN);
591 break;
593 case PC_RDR_XFR_BLOCK:
594 case PC_RDR_ESCAPE:
595 proto_tree_add_item_ret_uint(ccid_tree, hf_ccid_dwLength,
596 tvb, 1, 4, ENC_LITTLE_ENDIAN, &payload_len);
597 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
598 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
600 if (cmd == PC_RDR_ESCAPE) {
601 proto_tree_add_item(ccid_tree, hf_ccid_abRFU, tvb, 7, 3, ENC_NA);
602 } else {
603 proto_tree_add_item(ccid_tree, hf_ccid_bBWI, tvb, 7, 1, ENC_LITTLE_ENDIAN);
604 proto_tree_add_item(ccid_tree, hf_ccid_wLevelParameter, tvb, 8, 2, ENC_LITTLE_ENDIAN);
607 if (payload_len == 0)
608 break;
610 next_tvb = tvb_new_subset_length(tvb, 10, payload_len);
611 /* sent/received is from the perspective of the card reader */
612 pinfo->p2p_dir = P2P_DIR_SENT;
614 if (!dissector_try_payload_with_data(subdissector_table, next_tvb, pinfo, tree, true, urb)) {
615 call_data_dissector(next_tvb, pinfo, tree);
617 break;
619 case RDR_PC_DATA_BLOCK:
620 case RDR_PC_ESCAPE:
621 proto_tree_add_item_ret_uint(ccid_tree, hf_ccid_dwLength,
622 tvb, 1, 4, ENC_LITTLE_ENDIAN, &payload_len);
623 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
624 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
625 proto_tree_add_bitmask(ccid_tree, tvb, 7, hf_ccid_bStatus, ett_ccid_status, bStatus_fields, ENC_LITTLE_ENDIAN);
626 proto_tree_add_item(ccid_tree, hf_ccid_bError, tvb, 8, 1, ENC_LITTLE_ENDIAN);
627 if (cmd == RDR_PC_ESCAPE)
628 proto_tree_add_item(ccid_tree, hf_ccid_bRFU, tvb, 9, 1, ENC_LITTLE_ENDIAN);
629 else
630 proto_tree_add_item(ccid_tree, hf_ccid_bChainParameter, tvb, 9, 1, ENC_LITTLE_ENDIAN);
632 if (payload_len == 0)
633 break;
635 next_tvb = tvb_new_subset_length(tvb, 10, payload_len);
636 pinfo->p2p_dir = P2P_DIR_RECV;
638 if (!dissector_try_payload_with_data(subdissector_table, next_tvb, pinfo, tree, true, urb)) {
639 call_data_dissector(next_tvb, pinfo, tree);
641 break;
643 case RDR_PC_SLOT_STATUS:
644 proto_tree_add_item(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN);
645 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
646 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
647 proto_tree_add_bitmask(ccid_tree, tvb, 7, hf_ccid_bStatus, ett_ccid_status, bStatus_fields, ENC_LITTLE_ENDIAN);
648 proto_tree_add_item(ccid_tree, hf_ccid_bError, tvb, 8, 1, ENC_LITTLE_ENDIAN);
649 proto_tree_add_item(ccid_tree, hf_ccid_bClockStatus, tvb, 9, 1, ENC_LITTLE_ENDIAN);
650 break;
652 case RDR_PC_PARAMS:
653 proto_tree_add_item_ret_uint(ccid_tree, hf_ccid_dwLength, tvb, 1, 4, ENC_LITTLE_ENDIAN, &payload_len);
654 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 5, 1, ENC_LITTLE_ENDIAN);
655 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 6, 1, ENC_LITTLE_ENDIAN);
656 proto_tree_add_bitmask(ccid_tree, tvb, 7, hf_ccid_bStatus, ett_ccid_status, bStatus_fields, ENC_LITTLE_ENDIAN);
657 proto_tree_add_item(ccid_tree, hf_ccid_bError, tvb, 8, 1, ENC_LITTLE_ENDIAN);
658 proto_tree_add_item(ccid_tree, hf_ccid_bProtocolNum, tvb, 9, 1, ENC_LITTLE_ENDIAN);
660 /* abProtocolDataStructure */
661 bProtocolNum = tvb_get_uint8(tvb, 9);
662 switch (bProtocolNum)
664 case 0: /* T=0 */
665 if (payload_len > 0) {
666 protocol_tree = proto_tree_add_subtree(tree, tvb, 10, payload_len, ett_ccid_protocol_data_structure, NULL, "Protocol Data Structure for Protocol T=0");
667 proto_tree_add_item(protocol_tree, hf_ccid_bmFindexDindex, tvb, 10, 1, ENC_LITTLE_ENDIAN);
668 proto_tree_add_item(protocol_tree, hf_ccid_bmTCCKST0, tvb, 11, 1, ENC_LITTLE_ENDIAN);
669 proto_tree_add_item(protocol_tree, hf_ccid_bGuardTimeT0, tvb, 12, 1, ENC_LITTLE_ENDIAN);
670 proto_tree_add_item(protocol_tree, hf_ccid_bWaitingIntegerT0, tvb, 13, 1, ENC_LITTLE_ENDIAN);
671 proto_tree_add_item(protocol_tree, hf_ccid_bClockStop, tvb, 14, 1, ENC_LITTLE_ENDIAN);
673 break;
675 case 1: /* T=1 */
676 protocol_tree = proto_tree_add_subtree(tree, tvb, 10, payload_len, ett_ccid_protocol_data_structure, NULL, "Protocol Data Structure for Protocol T=1");
677 proto_tree_add_item(protocol_tree, hf_ccid_bmFindexDindex, tvb, 10, 1, ENC_LITTLE_ENDIAN);
678 proto_tree_add_item(protocol_tree, hf_ccid_bmTCCKST1, tvb, 11, 1, ENC_LITTLE_ENDIAN);
679 proto_tree_add_item(protocol_tree, hf_ccid_bGuardTimeT1, tvb, 12, 1, ENC_LITTLE_ENDIAN);
680 proto_tree_add_item(protocol_tree, hf_ccid_bmWaitingIntegersT1, tvb, 13, 1, ENC_LITTLE_ENDIAN);
681 proto_tree_add_item(protocol_tree, hf_ccid_bClockStop, tvb, 14, 1, ENC_LITTLE_ENDIAN);
682 proto_tree_add_item(protocol_tree, hf_ccid_bIFSC, tvb, 15, 1, ENC_LITTLE_ENDIAN);
683 proto_tree_add_item(protocol_tree, hf_ccid_bNadValue, tvb, 16, 1, ENC_LITTLE_ENDIAN);
684 break;
686 default:
687 next_tvb = tvb_new_subset_remaining(tvb, 10);
688 call_data_dissector(next_tvb, pinfo, tree);
690 break;
692 /*Interrupt IN*/
693 case RDR_PC_NOTIF_SLOT_CHNG:
694 proto_tree_add_bitmask(ccid_tree, tvb, 1,
695 hf_ccid_bmSlotICCState, ett_ccid_slot_change, bmSlotICCStateb0_fields,
696 ENC_LITTLE_ENDIAN);
697 len_remaining = tvb_reported_length_remaining (tvb, 2);
698 if (len_remaining <= 0)
699 break;
700 proto_tree_add_bitmask(ccid_tree, tvb, 2,
701 hf_ccid_bmSlotICCState, ett_ccid_slot_change, bmSlotICCStateb1_fields,
702 ENC_LITTLE_ENDIAN);
703 break;
705 case RDR_PC_HWERROR:
706 proto_tree_add_item(ccid_tree, hf_ccid_bSlot, tvb, 1, 1, ENC_LITTLE_ENDIAN);
707 proto_tree_add_item(ccid_tree, hf_ccid_bSeq, tvb, 2, 1, ENC_LITTLE_ENDIAN);
708 proto_tree_add_item(ccid_tree, hf_ccid_bHardwareErrorCode, tvb, 3, 1, ENC_LITTLE_ENDIAN);
709 break;
715 /* TODO: Try use "offset" instead of hardcoded constants */
716 return tvb_captured_length(tvb);
719 void
720 proto_register_ccid(void)
722 static hf_register_info hf[] = {
724 {&hf_ccid_bMessageType,
725 { "Message Type", "usbccid.bMessageType", FT_UINT8, BASE_HEX,
726 VALS(ccid_opcode_vals), 0x0, NULL, HFILL }},
727 {&hf_ccid_dwLength,
728 { "Packet Length", "usbccid.dwLength", FT_UINT32, BASE_DEC,
729 NULL, 0x0, NULL, HFILL }},
730 {&hf_ccid_bSlot,
731 { "Slot", "usbccid.bSlot", FT_UINT8, BASE_DEC,
732 NULL, 0x0, NULL, HFILL }},
733 {&hf_ccid_bSeq,
734 { "Sequence", "usbccid.bSeq", FT_UINT8, BASE_DEC,
735 NULL, 0x0, NULL, HFILL }},
736 {&hf_ccid_bStatus,
737 { "Status", "usbccid.bStatus", FT_UINT8, BASE_DEC,
738 NULL, 0x0, NULL, HFILL }},
739 {&hf_ccid_bStatus_bmIccStatus,
740 { "Status", "usbccid.bStatus.bmIccStatus", FT_UINT8, BASE_DEC,
741 VALS(ccid_status_icc_status_vals), 0x03, NULL, HFILL }},
742 {&hf_ccid_bStatus_bmCommandStatus,
743 { "Status", "usbccid.bStatus.bmCommandStatus", FT_UINT8, BASE_DEC,
744 VALS(ccid_status_cmd_status_vals), 0xC0, NULL, HFILL }},
745 {&hf_ccid_bError,
746 { "Error", "usbccid.bError", FT_UINT8, BASE_DEC,
747 NULL, 0x0, NULL, HFILL }},
748 {&hf_ccid_bRFU,
749 { "RFU", "usbccid.bRFU", FT_UINT8, BASE_HEX,
750 NULL, 0x0, NULL, HFILL }},
751 {&hf_ccid_abRFU,
752 { "RFU", "usbccid.abRFU", FT_BYTES, BASE_NONE,
753 NULL, 0x0, NULL, HFILL }},
754 {&hf_ccid_bChainParameter,
755 { "Chain Parameter", "usbccid.bChainParameter", FT_UINT8, BASE_DEC,
756 NULL, 0x0, NULL, HFILL }},
757 {&hf_ccid_bPowerSelect,
758 { "Voltage Level", "usbccid.bPowerSelect", FT_UINT8, BASE_HEX,
759 VALS(ccid_voltage_levels_vals), 0x0, NULL, HFILL }},
760 {&hf_ccid_bClockStatus,
761 { "Clock Status", "usbccid.bClockStatus", FT_UINT8, BASE_HEX,
762 VALS(ccid_clock_states_vals), 0x0, NULL, HFILL }},
763 {&hf_ccid_bProtocolNum,
764 { "Data Structure Type", "usbccid.bProtocolNum", FT_UINT8, BASE_HEX,
765 VALS(ccid_proto_structs_vals), 0x0, NULL, HFILL }},
766 {&hf_ccid_bBWI,
767 { "Block Wait Time Integer", "usbccid.bBWI", FT_UINT8, BASE_HEX,
768 NULL, 0x0, NULL, HFILL }},
769 {&hf_ccid_wLevelParameter,
770 { "Level Parameter", "usbccid.wLevelParameter", FT_UINT16, BASE_HEX,
771 NULL, 0x0, NULL, HFILL }},
772 {&hf_ccid_bcdCCID,
773 { "bcdCCID", "usbccid.bcdCCID", FT_UINT16, BASE_HEX,
774 NULL, 0x0, NULL, HFILL }},
775 {&hf_ccid_bMaxSlotIndex,
776 { "max slot index", "usbccid.bMaxSlotIndex", FT_UINT8, BASE_HEX,
777 NULL, 0x0, NULL, HFILL }},
778 {&hf_ccid_bVoltageSupport,
779 { "voltage support", "usbccid.bVoltageSupport", FT_UINT8, BASE_HEX,
780 NULL, 0x0, NULL, HFILL }},
781 {&hf_ccid_bVoltageSupport18,
782 { "1.8V", "usbccid.bVoltageSupport.18", FT_BOOLEAN, 8,
783 TFS(&tfs_supported_not_supported), 0x04, NULL, HFILL }},
784 {&hf_ccid_bVoltageSupport30,
785 { "3.0V", "usbccid.bVoltageSupport.30", FT_BOOLEAN, 8,
786 TFS(&tfs_supported_not_supported), 0x02, NULL, HFILL }},
787 {&hf_ccid_bVoltageSupport50,
788 { "5.0V", "usbccid.bVoltageSupport.50", FT_BOOLEAN, 8,
789 TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }},
790 {&hf_ccid_dwProtocols,
791 { "dwProtocols", "usbccid.dwProtocols", FT_UINT32, BASE_HEX,
792 NULL, 0x0, NULL, HFILL }},
793 {&hf_ccid_dwProtocols_t0,
794 { "T=0", "usbccid.dwProtocols.t0", FT_BOOLEAN, 32,
795 TFS(&tfs_supported_not_supported), 0x00000001, NULL, HFILL }},
796 {&hf_ccid_dwProtocols_t1,
797 { "T=1", "usbccid.dwProtocols.t1", FT_BOOLEAN, 32,
798 TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
799 {&hf_ccid_dwDefaultClock,
800 { "default clock frequency", "usbccid.dwDefaultClock",
801 FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_khz), 0x0, NULL, HFILL }},
802 {&hf_ccid_dwMaximumClock,
803 { "maximum clock frequency", "usbccid.dwMaximumClock",
804 FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_khz), 0x0, NULL, HFILL }},
805 {&hf_ccid_bNumClockSupported,
806 { "number of supported clock frequencies", "usbccid.bNumClockSupported",
807 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
808 {&hf_ccid_dwDataRate,
809 { "default ICC I/O data rate in bps", "usbccid.dwDataRate",
810 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
811 {&hf_ccid_dwMaxDataRate,
812 { "maximum ICC I/O data rate in bps", "usbccid.dwMaxDataRate",
813 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
814 {&hf_ccid_bNumDataRatesSupported,
815 { "number of supported data rates", "usbccid.bNumDataRatesSupported",
816 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
817 { &hf_ccid_dwMaxIFSD,
818 { "maximum IFSD supported", "usbccid.dwMaxIFSD",
819 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
820 {&hf_ccid_dwSynchProtocols,
821 { "supported protocol types", "usbccid.dwSynchProtocols",
822 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
823 {&hf_ccid_dwMechanical,
824 { "mechanical characteristics", "usbccid.dwMechanical",
825 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
826 {&hf_ccid_dwFeatures,
827 { "intelligent features", "usbccid.dwFeatures",
828 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
829 {&hf_ccid_dwFeatures_autoIccActivation,
830 { "Automatic activation of ICC on inserting",
831 "usbccid.dwFeatures.autoIccActivation", FT_BOOLEAN, 32,
832 TFS(&tfs_supported_not_supported), 0x00000004, NULL, HFILL }},
833 {&hf_ccid_dwFeatures_autoIccVoltSelect,
834 { "Automatic ICC voltage selection",
835 "usbccid.dwFeatures.autoIccVoltSelect", FT_BOOLEAN, 32,
836 TFS(&tfs_supported_not_supported), 0x00000008, NULL, HFILL }},
837 {&hf_ccid_dwFeatures_autoParam,
838 { "Automatic parameter configuration based on ATR",
839 "usbccid.dwFeatures.autoParam", FT_BOOLEAN, 32,
840 TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
841 {&hf_ccid_dwFeatures_autoIccClk,
842 { "Automatic ICC clock frequency change",
843 "usbccid.dwFeatures.autoIccClk", FT_BOOLEAN, 32,
844 TFS(&tfs_supported_not_supported), 0x00000010, NULL, HFILL }},
845 {&hf_ccid_dwFeatures_autoBaudRate,
846 { "Automatic baud rate change",
847 "usbccid.dwFeatures.autoBaudRate", FT_BOOLEAN, 32,
848 TFS(&tfs_supported_not_supported), 0x00000020, NULL, HFILL }},
849 {&hf_ccid_dwFeatures_autoParamNegotiation,
850 { "Automatic parameters negotiation",
851 "usbccid.dwFeatures.autoParamNegotiation", FT_BOOLEAN, 32,
852 TFS(&tfs_supported_not_supported), 0x00000040, NULL, HFILL }},
853 {&hf_ccid_dwFeatures_autoPPS,
854 { "Automatic PPS",
855 "usbccid.dwFeatures.autoPPS", FT_BOOLEAN, 32,
856 TFS(&tfs_supported_not_supported), 0x00000080, NULL, HFILL }},
857 {&hf_ccid_dwFeatures_stopIccClk,
858 { "CCID can set ICC in clock stop mode",
859 "usbccid.dwFeatures.stopIccClk", FT_BOOLEAN, 32,
860 TFS(&tfs_supported_not_supported), 0x00000100, NULL, HFILL }},
861 {&hf_ccid_dwFeatures_nadValNot0accept,
862 { "NAD value other than 00 accepted",
863 "usbccid.dwFeatures.nadValNot0accept", FT_BOOLEAN, 32,
864 TFS(&tfs_supported_not_supported), 0x00000200, NULL, HFILL }},
865 {&hf_ccid_dwFeatures_autoIfsd,
866 { "Automatic IFSD exchange as first exchange",
867 "usbccid.dwFeatures.autoIfsd", FT_BOOLEAN, 32,
868 TFS(&tfs_supported_not_supported), 0x00000400, NULL, HFILL }},
869 {&hf_ccid_dwFeatures_levelExchangeTDPU,
870 { "TPDU level exchanges",
871 "usbccid.dwFeatures.levelExchangeTDPU", FT_BOOLEAN, 32,
872 TFS(&tfs_supported_not_supported), 0x00010000, NULL, HFILL }},
873 {&hf_ccid_dwFeatures_levelExchangeShortAPDU,
874 { "Short APDU level exchange",
875 "usbccid.dwFeatures.levelExchangeShortAPDU", FT_BOOLEAN, 32,
876 TFS(&tfs_supported_not_supported), 0x00020000, NULL, HFILL }},
877 {&hf_ccid_dwFeatures_levelExchangeShortExtendedAPDU,
878 { "Short and Extended APDU level exchange",
879 "usbccid.dwFeatures.levelExchangeShortExtendedAPDU", FT_BOOLEAN, 32,
880 TFS(&tfs_supported_not_supported), 0x00040000, NULL, HFILL }},
881 {&hf_ccid_dwFeatures_UsbWakeUp,
882 { "USB Wake up signaling supported on card insertion and removal",
883 "usbccid.dwFeatures.UsbWakeUp", FT_BOOLEAN, 32,
884 TFS(&tfs_supported_not_supported), 0x00100000, NULL, HFILL }},
885 {&hf_ccid_dwMaxCCIDMessageLength,
886 { "maximum CCID message length", "usbccid.dwMaxCCIDMessageLength",
887 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
888 {&hf_ccid_bClassGetResponse,
889 { "default class for Get Response", "usbccid.hf_ccid_bClassGetResponse",
890 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
891 {&hf_ccid_bClassEnvelope,
892 { "default class for Envelope", "usbccid.hf_ccid_bClassEnvelope",
893 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
894 {&hf_ccid_wLcdLayout,
895 { "LCD layout", "usbccid.hf_ccid_wLcdLayout",
896 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
897 {&hf_ccid_wLcdLayout_lines,
898 { "Lines", "usbccid.hf_ccid_wLcdLayout.lines",
899 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
900 {&hf_ccid_wLcdLayout_chars,
901 { "Characters per line", "usbccid.hf_ccid_wLcdLayout.chars",
902 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
903 {&hf_ccid_bPINSupport,
904 { "PIN support", "usbccid.hf_ccid_bPINSupport",
905 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
906 {&hf_ccid_bPINSupport_modify,
907 { "PIN modification", "usbccid.hf_ccid_bPINSupport.modify",
908 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x02, NULL, HFILL }},
909 {&hf_ccid_bPINSupport_vrfy,
910 { "PIN verification", "usbccid.hf_ccid_bPINSupport.verify",
911 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }},
912 {&hf_ccid_bMaxCCIDBusySlots,
913 { "maximum number of busy slots", "usbccid.hf_ccid_bMaxCCIDBusySlots",
914 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
915 {&hf_ccid_Reserved,
916 { "Reserved for Future Use", "usbccid.hf_ccid_Reserved",
917 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
918 { &hf_ccid_bmSlotICCState,
919 { "Slot ICC State", "usbccid.hf_ccid_bmSlotICCState",
920 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
921 { &hf_ccid_bmSlotICCState_slot0Current,
922 { "Slot 0 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot0Current",
923 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01, NULL, HFILL } },
924 { &hf_ccid_bmSlotICCState_slot0Changed,
925 { "Slot 0 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot0Changed",
926 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02, NULL, HFILL } },
927 { &hf_ccid_bmSlotICCState_slot1Current,
928 { "Slot 1 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot1Current",
929 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x04, NULL, HFILL } },
930 { &hf_ccid_bmSlotICCState_slot1Changed,
931 { "Slot 1 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot1Changed",
932 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08, NULL, HFILL } },
933 { &hf_ccid_bmSlotICCState_slot2Current,
934 { "Slot 2 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot2Current",
935 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x10, NULL, HFILL } },
936 { &hf_ccid_bmSlotICCState_slot2Changed,
937 { "Slot 2 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot2Changed",
938 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL, HFILL } },
939 { &hf_ccid_bmSlotICCState_slot3Current,
940 { "Slot 3 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot3Current",
941 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x40, NULL, HFILL } },
942 { &hf_ccid_bmSlotICCState_slot3Changed,
943 { "Slot 3 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot3Changed",
944 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80, NULL, HFILL } },
945 { &hf_ccid_bmSlotICCState_slot4Current,
946 { "Slot 4 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot4Current",
947 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01, NULL, HFILL } },
948 { &hf_ccid_bmSlotICCState_slot4Changed,
949 { "Slot 4 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot4Changed",
950 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02, NULL, HFILL } },
951 { &hf_ccid_bmSlotICCState_slot5Current,
952 { "Slot 5 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot5Current",
953 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x04, NULL, HFILL } },
954 { &hf_ccid_bmSlotICCState_slot5Changed,
955 { "Slot 5 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot5Changed",
956 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08, NULL, HFILL } },
957 { &hf_ccid_bmSlotICCState_slot6Current,
958 { "Slot 6 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot6Current",
959 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x10, NULL, HFILL } },
960 { &hf_ccid_bmSlotICCState_slot6Changed,
961 { "Slot 6 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot6Changed",
962 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL, HFILL } },
963 { &hf_ccid_bmSlotICCState_slot7Current,
964 { "Slot 7 Current Status", "usbccid.hf_ccid_bmSlotICCState.slot7Current",
965 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x40, NULL, HFILL } },
966 { &hf_ccid_bmSlotICCState_slot7Changed,
967 { "Slot 7 Status changed", "usbccid.hf_ccid_bmSlotICCState.slot7Changed",
968 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80, NULL, HFILL } },
969 { &hf_ccid_bHardwareErrorCode,
970 { "Hardware Error Code", "usbccid.hf_ccid_bHardwareErrorCode",
971 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
972 {&hf_ccid_bmFindexDindex,
973 { "Fi/Di selecting clock rate", "usbccid.bmFindexDindex", FT_UINT8, BASE_HEX,
974 NULL, 0x0, NULL, HFILL }},
975 {&hf_ccid_bmTCCKST0,
976 { "Convention used", "usbccid.bmTCCKST0", FT_UINT8, BASE_HEX,
977 NULL, 0x0, NULL, HFILL }},
978 {&hf_ccid_bmTCCKST1,
979 { "Checksum type - Convention used", "usbccid.bmTCCKST1", FT_UINT8, BASE_HEX,
980 NULL, 0x0, NULL, HFILL }},
981 {&hf_ccid_bGuardTimeT0,
982 { "Extra Guardtime between two characters", "usbccid.bGuardTimeT0", FT_UINT8, BASE_HEX,
983 NULL, 0x0, NULL, HFILL }},
984 {&hf_ccid_bGuardTimeT1,
985 { "Extra Guardtime", "usbccid.bGuardTimeT1", FT_UINT8, BASE_HEX,
986 NULL, 0x0, NULL, HFILL }},
987 {&hf_ccid_bmWaitingIntegersT1,
988 { "BWI - CWI", "usbccid.bmWaitingIntegersT1", FT_UINT8, BASE_HEX,
989 NULL, 0x0, NULL, HFILL }},
990 {&hf_ccid_bClockStop,
991 { "ICC Clock Stop Support", "usbccid.bClockStop", FT_UINT8, BASE_HEX,
992 NULL, 0x0, NULL, HFILL }},
993 {&hf_ccid_bIFSC,
994 { "Size of negotiated IFSC", "usbccid.bIFSC", FT_UINT8, BASE_HEX,
995 NULL, 0x0, NULL, HFILL }},
996 {&hf_ccid_bNadValue,
997 { "NAD", "usbccid.bNadValue", FT_UINT8, BASE_HEX,
998 NULL, 0x0, NULL, HFILL }},
999 {&hf_ccid_bWaitingIntegerT0,
1000 { "WI for T= 0 used to define WWT", "usbccid.bWaitingIntegerT0", FT_UINT8, BASE_HEX,
1001 NULL, 0x0, NULL, HFILL }},
1004 static int *ett[] = {
1005 &ett_ccid,
1006 &ett_ccid_desc,
1007 &ett_ccid_protocol_data_structure,
1008 &ett_ccid_voltage_level,
1009 &ett_ccid_protocols,
1010 &ett_ccid_features,
1011 &ett_ccid_lcd_layout,
1012 &ett_ccid_pin_support,
1013 &ett_ccid_slot_change,
1014 &ett_ccid_status
1017 module_t *pref_mod;
1019 proto_ccid = proto_register_protocol("USB CCID", "USBCCID", "usbccid");
1020 proto_register_field_array(proto_ccid, hf, array_length(hf));
1021 proto_register_subtree_array(ett, array_length(ett));
1023 pref_mod = prefs_register_protocol_obsolete(proto_ccid);
1024 prefs_register_obsolete_preference(pref_mod, "prtype");
1026 usb_ccid_handle = register_dissector("usbccid", dissect_ccid, proto_ccid);
1027 usb_ccid_descr_handle = register_dissector("usbccid.descriptor", dissect_usb_ccid_descriptor, proto_ccid);
1029 subdissector_table = register_decode_as_next_proto(proto_ccid, "usbccid.subdissector", "USB CCID payload", NULL);
1032 /* Handler registration */
1033 void
1034 proto_reg_handoff_ccid(void)
1036 dissector_add_uint("usb.descriptor", IF_CLASS_SMART_CARD, usb_ccid_descr_handle);
1038 dissector_add_uint("usb.bulk", IF_CLASS_SMART_CARD, usb_ccid_handle);
1040 dissector_add_for_decode_as("usb.device", usb_ccid_handle);
1041 dissector_add_for_decode_as("usb.product", usb_ccid_handle);
1042 dissector_add_for_decode_as("usb.protocol", usb_ccid_handle);
1046 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1048 * Local variables:
1049 * c-basic-offset: 4
1050 * tab-width: 8
1051 * indent-tabs-mode: nil
1052 * End:
1054 * ex: set shiftwidth=4 tabstop=8 expandtab:
1055 * :indentSize=4:tabSize=8:noTabs=true: