1214456Srpaulo/*
2214456Srpaulo * Copyright 2009 Bert Vermeulen <bert@biot.com>
3214456Srpaulo *
4214456Srpaulo * Redistribution and use in source and binary forms, with or without
5214456Srpaulo * modification, are permitted provided that: (1) source code distributions
6214456Srpaulo * retain the above copyright notice and this paragraph in its entirety, (2)
7214456Srpaulo * distributions including binary code include the above copyright notice and
8214456Srpaulo * this paragraph in its entirety in the documentation or other materials
9214456Srpaulo * provided with the distribution, and (3) all advertising materials mentioning
10214456Srpaulo * features or use of this software display the following acknowledgement:
11214456Srpaulo * ``This product includes software developed by Paolo Abeni.''
12214456Srpaulo * The name of author may not be used to endorse or promote products derived
13214456Srpaulo * from this software without specific prior written permission.
14214456Srpaulo * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
15214456Srpaulo * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
16214456Srpaulo * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17214456Srpaulo *
18214456Srpaulo * Support for USB packets
19214456Srpaulo *
20214456Srpaulo */
21214456Srpaulo
22214456Srpaulo#ifdef HAVE_CONFIG_H
23214456Srpaulo#include "config.h"
24214456Srpaulo#endif
25214456Srpaulo
26214456Srpaulo#include <tcpdump-stdinc.h>
27214456Srpaulo
28214456Srpaulo#include <pcap.h>
29214456Srpaulo#include <stdio.h>
30214456Srpaulo#include <string.h>
31214456Srpaulo
32214456Srpaulo#include "interface.h"
33214456Srpaulo
34214456Srpaulo
35214456Srpaulo#if defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX)
36214456Srpaulo#include <pcap/usb.h>
37214456Srpaulo
38214456Srpaulo/* returns direction: 1=inbound 2=outbound -1=invalid */
39214456Srpaulostatic int
40214456Srpauloget_direction(int transfer_type, int event_type)
41214456Srpaulo{
42214456Srpaulo	int direction;
43214456Srpaulo
44214456Srpaulo	direction = -1;
45214456Srpaulo	switch(transfer_type){
46214456Srpaulo	case URB_BULK:
47214456Srpaulo	case URB_CONTROL:
48214456Srpaulo	case URB_ISOCHRONOUS:
49214456Srpaulo		switch(event_type)
50214456Srpaulo		{
51214456Srpaulo		case URB_SUBMIT:
52214456Srpaulo			direction = 2;
53214456Srpaulo			break;
54214456Srpaulo		case URB_COMPLETE:
55214456Srpaulo		case URB_ERROR:
56214456Srpaulo			direction = 1;
57214456Srpaulo			break;
58214456Srpaulo		default:
59214456Srpaulo			direction = -1;
60214456Srpaulo		}
61214456Srpaulo		break;
62214456Srpaulo	case URB_INTERRUPT:
63214456Srpaulo		switch(event_type)
64214456Srpaulo		{
65214456Srpaulo		case URB_SUBMIT:
66214456Srpaulo			direction = 1;
67214456Srpaulo			break;
68214456Srpaulo		case URB_COMPLETE:
69214456Srpaulo		case URB_ERROR:
70214456Srpaulo			direction = 2;
71214456Srpaulo			break;
72214456Srpaulo		default:
73214456Srpaulo			direction = -1;
74214456Srpaulo		}
75214456Srpaulo		break;
76214456Srpaulo	 default:
77214456Srpaulo		direction = -1;
78214456Srpaulo	}
79214456Srpaulo
80214456Srpaulo	return direction;
81214456Srpaulo}
82214456Srpaulo
83214456Srpaulostatic void
84214456Srpaulousb_header_print(const pcap_usb_header *uh)
85214456Srpaulo{
86214456Srpaulo	int direction;
87214456Srpaulo
88214456Srpaulo	switch(uh->transfer_type)
89214456Srpaulo	{
90214456Srpaulo		case URB_ISOCHRONOUS:
91214456Srpaulo			printf("ISOCHRONOUS");
92214456Srpaulo			break;
93214456Srpaulo		case URB_INTERRUPT:
94214456Srpaulo			printf("INTERRUPT");
95214456Srpaulo			break;
96214456Srpaulo		case URB_CONTROL:
97214456Srpaulo			printf("CONTROL");
98214456Srpaulo			break;
99214456Srpaulo		case URB_BULK:
100214456Srpaulo			printf("BULK");
101214456Srpaulo			break;
102214456Srpaulo		default:
103214456Srpaulo			printf(" ?");
104214456Srpaulo	}
105214456Srpaulo
106214456Srpaulo	switch(uh->event_type)
107214456Srpaulo	{
108214456Srpaulo		case URB_SUBMIT:
109214456Srpaulo			printf(" SUBMIT");
110214456Srpaulo			break;
111214456Srpaulo		case URB_COMPLETE:
112214456Srpaulo			printf(" COMPLETE");
113214456Srpaulo			break;
114214456Srpaulo		case URB_ERROR:
115214456Srpaulo			printf(" ERROR");
116214456Srpaulo			break;
117214456Srpaulo		default:
118214456Srpaulo			printf(" ?");
119214456Srpaulo	}
120214456Srpaulo
121214456Srpaulo	direction = get_direction(uh->transfer_type, uh->event_type);
122214456Srpaulo	if(direction == 1)
123214456Srpaulo		printf(" from");
124214456Srpaulo	else if(direction == 2)
125214456Srpaulo		printf(" to");
126214456Srpaulo	printf(" %d:%d:%d", uh->bus_id, uh->device_address, uh->endpoint_number & 0x7f);
127214456Srpaulo}
128214456Srpaulo
129214456Srpaulo/*
130214456Srpaulo * This is the top level routine of the printer for captures with a
131214456Srpaulo * 48-byte header.
132214456Srpaulo *
133214456Srpaulo * 'p' points to the header of the packet, 'h->ts' is the timestamp,
134214456Srpaulo * 'h->len' is the length of the packet off the wire, and 'h->caplen'
135214456Srpaulo * is the number of bytes actually captured.
136214456Srpaulo */
137214456Srpaulou_int
138214456Srpaulousb_linux_48_byte_print(const struct pcap_pkthdr *h, register const u_char *p)
139214456Srpaulo{
140214456Srpaulo	if (h->caplen < sizeof(pcap_usb_header)) {
141214456Srpaulo		printf("[|usb]");
142214456Srpaulo		return(sizeof(pcap_usb_header));
143214456Srpaulo	}
144214456Srpaulo
145214456Srpaulo	usb_header_print((const pcap_usb_header *) p);
146214456Srpaulo
147214456Srpaulo	return(sizeof(pcap_usb_header));
148214456Srpaulo}
149214456Srpaulo
150214456Srpaulo#ifdef DLT_USB_LINUX_MMAPPED
151214456Srpaulo/*
152214456Srpaulo * This is the top level routine of the printer for captures with a
153214456Srpaulo * 64-byte header.
154214456Srpaulo *
155214456Srpaulo * 'p' points to the header of the packet, 'h->ts' is the timestamp,
156214456Srpaulo * 'h->len' is the length of the packet off the wire, and 'h->caplen'
157214456Srpaulo * is the number of bytes actually captured.
158214456Srpaulo */
159214456Srpaulou_int
160214456Srpaulousb_linux_64_byte_print(const struct pcap_pkthdr *h, register const u_char *p)
161214456Srpaulo{
162214456Srpaulo	if (h->caplen < sizeof(pcap_usb_header_mmapped)) {
163214456Srpaulo		printf("[|usb]");
164214456Srpaulo		return(sizeof(pcap_usb_header_mmapped));
165214456Srpaulo	}
166214456Srpaulo
167214456Srpaulo	usb_header_print((const pcap_usb_header *) p);
168214456Srpaulo
169214456Srpaulo	return(sizeof(pcap_usb_header_mmapped));
170214456Srpaulo}
171214456Srpaulo#endif /* DLT_USB_LINUX_MMAPPED */
172214456Srpaulo
173214456Srpaulo#endif /* defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX) */
174214456Srpaulo
175