diff options
Diffstat (limited to 'drivers/usb/mon/mon_text.c')
-rw-r--r-- | drivers/usb/mon/mon_text.c | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 755a4570477f..26266b30028e 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -19,11 +19,16 @@ | |||
19 | #define DATA_MAX 32 | 19 | #define DATA_MAX 32 |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * Defined by USB 2.0 clause 9.3, table 9.2. | ||
23 | */ | ||
24 | #define SETUP_MAX 8 | ||
25 | |||
26 | /* | ||
22 | * This limit exists to prevent OOMs when the user process stops reading. | 27 | * This limit exists to prevent OOMs when the user process stops reading. |
23 | */ | 28 | */ |
24 | #define EVENT_MAX 25 | 29 | #define EVENT_MAX 25 |
25 | 30 | ||
26 | #define PRINTF_DFL 120 | 31 | #define PRINTF_DFL 130 |
27 | 32 | ||
28 | struct mon_event_text { | 33 | struct mon_event_text { |
29 | struct list_head e_link; | 34 | struct list_head e_link; |
@@ -33,7 +38,9 @@ struct mon_event_text { | |||
33 | unsigned int tstamp; | 38 | unsigned int tstamp; |
34 | int length; /* Depends on type: xfer length or act length */ | 39 | int length; /* Depends on type: xfer length or act length */ |
35 | int status; | 40 | int status; |
41 | char setup_flag; | ||
36 | char data_flag; | 42 | char data_flag; |
43 | unsigned char setup[SETUP_MAX]; | ||
37 | unsigned char data[DATA_MAX]; | 44 | unsigned char data[DATA_MAX]; |
38 | }; | 45 | }; |
39 | 46 | ||
@@ -64,6 +71,22 @@ static void mon_text_dtor(void *, kmem_cache_t *, unsigned long); | |||
64 | * This is called with the whole mon_bus locked, so no additional lock. | 71 | * This is called with the whole mon_bus locked, so no additional lock. |
65 | */ | 72 | */ |
66 | 73 | ||
74 | static inline char mon_text_get_setup(struct mon_event_text *ep, | ||
75 | struct urb *urb, char ev_type) | ||
76 | { | ||
77 | |||
78 | if (!usb_pipecontrol(urb->pipe) || ev_type != 'S') | ||
79 | return '-'; | ||
80 | |||
81 | if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP) | ||
82 | return 'D'; | ||
83 | if (urb->setup_packet == NULL) | ||
84 | return 'Z'; /* '0' would be not as pretty. */ | ||
85 | |||
86 | memcpy(ep->setup, urb->setup_packet, SETUP_MAX); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
67 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | 90 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, |
68 | int len, char ev_type) | 91 | int len, char ev_type) |
69 | { | 92 | { |
@@ -90,7 +113,6 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | |||
90 | 113 | ||
91 | /* | 114 | /* |
92 | * Bulk is easy to shortcut reliably. | 115 | * Bulk is easy to shortcut reliably. |
93 | * XXX Control needs setup packet taken. | ||
94 | * XXX Other pipe types need consideration. Currently, we overdo it | 116 | * XXX Other pipe types need consideration. Currently, we overdo it |
95 | * and collect garbage for them: better more than less. | 117 | * and collect garbage for them: better more than less. |
96 | */ | 118 | */ |
@@ -144,6 +166,7 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb, | |||
144 | /* Collecting status makes debugging sense for submits, too */ | 166 | /* Collecting status makes debugging sense for submits, too */ |
145 | ep->status = urb->status; | 167 | ep->status = urb->status; |
146 | 168 | ||
169 | ep->setup_flag = mon_text_get_setup(ep, urb, ev_type); | ||
147 | ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type); | 170 | ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type); |
148 | 171 | ||
149 | rp->nevents++; | 172 | rp->nevents++; |
@@ -299,10 +322,25 @@ static ssize_t mon_text_read(struct file *file, char __user *buf, | |||
299 | default: /* PIPE_BULK */ utype = 'B'; | 322 | default: /* PIPE_BULK */ utype = 'B'; |
300 | } | 323 | } |
301 | cnt += snprintf(pbuf + cnt, limit - cnt, | 324 | cnt += snprintf(pbuf + cnt, limit - cnt, |
302 | "%lx %u %c %c%c:%03u:%02u %d %d", | 325 | "%lx %u %c %c%c:%03u:%02u", |
303 | ep->id, ep->tstamp, ep->type, | 326 | ep->id, ep->tstamp, ep->type, |
304 | utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe), | 327 | utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe)); |
305 | ep->status, ep->length); | 328 | |
329 | if (ep->setup_flag == 0) { /* Setup packet is present and captured */ | ||
330 | cnt += snprintf(pbuf + cnt, limit - cnt, | ||
331 | " s %02x %02x %04x %04x %04x", | ||
332 | ep->setup[0], | ||
333 | ep->setup[1], | ||
334 | (ep->setup[3] << 8) | ep->setup[2], | ||
335 | (ep->setup[5] << 8) | ep->setup[4], | ||
336 | (ep->setup[7] << 8) | ep->setup[6]); | ||
337 | } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */ | ||
338 | cnt += snprintf(pbuf + cnt, limit - cnt, | ||
339 | " %c __ __ ____ ____ ____", ep->setup_flag); | ||
340 | } else { /* No setup for this kind of URB */ | ||
341 | cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status); | ||
342 | } | ||
343 | cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length); | ||
306 | 344 | ||
307 | if ((data_len = ep->length) > 0) { | 345 | if ((data_len = ep->length) > 0) { |
308 | if (ep->data_flag == 0) { | 346 | if (ep->data_flag == 0) { |