xref: /netbsd-src/external/bsd/tcpdump/dist/print-usb.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*
2  * Copyright 2009 Bert Vermeulen <bert@biot.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that: (1) source code distributions
6  * retain the above copyright notice and this paragraph in its entirety, (2)
7  * distributions including binary code include the above copyright notice and
8  * this paragraph in its entirety in the documentation or other materials
9  * provided with the distribution, and (3) all advertising materials mentioning
10  * features or use of this software display the following acknowledgement:
11  * ``This product includes software developed by Paolo Abeni.''
12  * The name of author may not be used to endorse or promote products derived
13  * from this software without specific prior written permission.
14  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * Support for USB packets
19  *
20  */
21 
22 #include <sys/cdefs.h>
23 #ifndef lint
24 __RCSID("$NetBSD: print-usb.c,v 1.3 2017/02/05 04:05:05 spz Exp $");
25 #endif
26 
27 /* \summary: USB printer */
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <netdissect-stdinc.h>
34 
35 #include "netdissect.h"
36 
37 
38 #if defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX)
39 #include <pcap/usb.h>
40 
41 static const char tstr[] = "[|usb]";
42 
43 /* returns direction: 1=inbound 2=outbound -1=invalid */
44 static int
45 get_direction(int transfer_type, int event_type)
46 {
47 	int direction;
48 
49 	direction = -1;
50 	switch(transfer_type){
51 	case URB_BULK:
52 	case URB_CONTROL:
53 	case URB_ISOCHRONOUS:
54 		switch(event_type)
55 		{
56 		case URB_SUBMIT:
57 			direction = 2;
58 			break;
59 		case URB_COMPLETE:
60 		case URB_ERROR:
61 			direction = 1;
62 			break;
63 		default:
64 			direction = -1;
65 		}
66 		break;
67 	case URB_INTERRUPT:
68 		switch(event_type)
69 		{
70 		case URB_SUBMIT:
71 			direction = 1;
72 			break;
73 		case URB_COMPLETE:
74 		case URB_ERROR:
75 			direction = 2;
76 			break;
77 		default:
78 			direction = -1;
79 		}
80 		break;
81 	 default:
82 		direction = -1;
83 	}
84 
85 	return direction;
86 }
87 
88 static void
89 usb_header_print(netdissect_options *ndo, const pcap_usb_header *uh)
90 {
91 	int direction;
92 
93 	switch(uh->transfer_type)
94 	{
95 		case URB_ISOCHRONOUS:
96 			ND_PRINT((ndo, "ISOCHRONOUS"));
97 			break;
98 		case URB_INTERRUPT:
99 			ND_PRINT((ndo, "INTERRUPT"));
100 			break;
101 		case URB_CONTROL:
102 			ND_PRINT((ndo, "CONTROL"));
103 			break;
104 		case URB_BULK:
105 			ND_PRINT((ndo, "BULK"));
106 			break;
107 		default:
108 			ND_PRINT((ndo, " ?"));
109 	}
110 
111 	switch(uh->event_type)
112 	{
113 		case URB_SUBMIT:
114 			ND_PRINT((ndo, " SUBMIT"));
115 			break;
116 		case URB_COMPLETE:
117 			ND_PRINT((ndo, " COMPLETE"));
118 			break;
119 		case URB_ERROR:
120 			ND_PRINT((ndo, " ERROR"));
121 			break;
122 		default:
123 			ND_PRINT((ndo, " ?"));
124 	}
125 
126 	direction = get_direction(uh->transfer_type, uh->event_type);
127 	if(direction == 1)
128 		ND_PRINT((ndo, " from"));
129 	else if(direction == 2)
130 		ND_PRINT((ndo, " to"));
131 	ND_PRINT((ndo, " %d:%d:%d", uh->bus_id, uh->device_address, uh->endpoint_number & 0x7f));
132 }
133 
134 /*
135  * This is the top level routine of the printer for captures with a
136  * 48-byte header.
137  *
138  * 'p' points to the header of the packet, 'h->ts' is the timestamp,
139  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
140  * is the number of bytes actually captured.
141  */
142 u_int
143 usb_linux_48_byte_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
144                         register const u_char *p)
145 {
146 	if (h->caplen < sizeof(pcap_usb_header)) {
147 		ND_PRINT((ndo, "%s", tstr));
148 		return(sizeof(pcap_usb_header));
149 	}
150 
151 	usb_header_print(ndo, (const pcap_usb_header *) p);
152 
153 	return(sizeof(pcap_usb_header));
154 }
155 
156 #ifdef DLT_USB_LINUX_MMAPPED
157 /*
158  * This is the top level routine of the printer for captures with a
159  * 64-byte header.
160  *
161  * 'p' points to the header of the packet, 'h->ts' is the timestamp,
162  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
163  * is the number of bytes actually captured.
164  */
165 u_int
166 usb_linux_64_byte_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
167                         register const u_char *p)
168 {
169 	if (h->caplen < sizeof(pcap_usb_header_mmapped)) {
170 		ND_PRINT((ndo, "%s", tstr));
171 		return(sizeof(pcap_usb_header_mmapped));
172 	}
173 
174 	usb_header_print(ndo, (const pcap_usb_header *) p);
175 
176 	return(sizeof(pcap_usb_header_mmapped));
177 }
178 #endif /* DLT_USB_LINUX_MMAPPED */
179 
180 #endif /* defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX) */
181 
182