forked from JohnDMcMaster/usbrply
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bulk.cpp
161 lines (136 loc) · 3.33 KB
/
bulk.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <stdio.h>
#include <pcap.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include "uvd/util/error.h"
#include "uvd/util/util.h"
#include <limits.h>
#include "linux/usb/ch9.h"
#include "util.cpp"
unsigned int g_min_packet = 0;
unsigned int g_cur_packet = 0;
unsigned int g_max_packet = UINT_MAX;
bool g_error = false;
bool g_halt_error = true;
bool g_verbose = false;
FILE *g_out;
#define dbg(...) do { \
if (g_verbose) { printf(__VA_ARGS__); } \
} while(0)
void loop_cb(u_char *args, const struct pcap_pkthdr *header,
const u_char *packet) {
uint8_t *dat_cur = 0;
unsigned int len = 0;
usb_urb_t *urb = NULL;
size_t remaining_bytes = 0;
++g_cur_packet;
if (g_cur_packet < g_min_packet || g_cur_packet > g_max_packet) {
//printf("//Skipping packet %d\n", g_cur_packet);
return;
}
if (header->caplen != header->len) {
printf("packet %d: malformed, caplen %d != len %d\n",
g_cur_packet, header->caplen, header->len );
g_error = true;
return;
}
len = header->len;
remaining_bytes = len;
dat_cur = (uint8_t *)packet;
dbg("PACKET %u: length %u\n", g_cur_packet, len);
//caplen is actual length, len is reported
urb = (usb_urb_t *)dat_cur;
remaining_bytes -= sizeof(*urb);
dat_cur += sizeof(*urb);
if (g_verbose) {
printf("Packet %d (header size: %u)\n", g_cur_packet, sizeof(*urb));
print_urb(urb);
}
if (urb->type == URB_ERROR) {
printf("oh noes!\n");
if (g_halt_error) {
exit(1);
}
}
if (urb->transfer_type != URB_BULK) {
return;
}
if (URB_IS_IN(urb)) {
if (urb->type == URB_COMPLETE) {
int rc = fwrite((const void *)dat_cur, 1, urb->data_length, g_out);
if (rc != (int)urb->data_length) {
printf("Failed write (%d), expected %d on 0x%08X\n",
rc, urb->data_length, (int)urb->data);
exit(1);
}
}
}
}
void usage() {
printf("uvusbreplay [options] <input .cap>\n");
printf("Options:\n");
printf("-r <min-max>: use packet range, default all, 1 indexed (since Wireshark does), inclusive\n");
printf("-k: format output for Linux kernel (default)\n");
printf("-l: format output for libusb\n");
printf("-n: no packet numbering\n");
}
int main(int argc, char *argv[])
{
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *p = NULL;
opterr = 0;
while (true) {
int c = getopt(argc, argv, "r:klh?vsfn");
if (c == -1) {
break;
}
switch (c)
{
case 'r':
{
if (UV_FAILED(parseNumericRangeString(optarg, &g_min_packet, &g_max_packet))) {
printf("Invalid range string %s\n", optarg);
usage();
exit(1);
}
break;
}
case 'h':
case '?':
usage();
exit(1);
break;
case 'v':
g_verbose = true;
break;
default:
printf("Unknown argument %c\n", c);
usage();
exit(1);
}
}
std::string fileNameIn = "in.cap";
std::string fileNameOut = "out.bin";
if (optind < argc) {
fileNameIn = argv[optind];
++optind;
}
if (optind < argc) {
fileNameOut = argv[optind];
++optind;
}
dbg("parsing from range %u to %u\n", g_min_packet, g_max_packet);
p = pcap_open_offline(fileNameIn.c_str(), errbuf);
if (p == NULL) {
printf("failed to open %s\n", fileNameIn.c_str());
exit(1);
}
g_out = fopen(fileNameOut.c_str(), "w");
if (!g_out) {
printf("failed to open %s\n", fileNameOut.c_str());
exit(1);
}
pcap_loop(p, -1, loop_cb, NULL);
return 0;
}