Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * The USB Monitor, inspired by Dave Harding's USBMon.
4 : : *
5 : : * This is a text format reader.
6 : : */
7 : :
8 : : #include <linux/kernel.h>
9 : : #include <linux/list.h>
10 : : #include <linux/usb.h>
11 : : #include <linux/slab.h>
12 : : #include <linux/sched/signal.h>
13 : : #include <linux/time.h>
14 : : #include <linux/ktime.h>
15 : : #include <linux/export.h>
16 : : #include <linux/mutex.h>
17 : : #include <linux/debugfs.h>
18 : : #include <linux/scatterlist.h>
19 : : #include <linux/uaccess.h>
20 : :
21 : : #include "usb_mon.h"
22 : :
23 : : /*
24 : : * No, we do not want arbitrarily long data strings.
25 : : * Use the binary interface if you want to capture bulk data!
26 : : */
27 : : #define DATA_MAX 32
28 : :
29 : : /*
30 : : * Defined by USB 2.0 clause 9.3, table 9.2.
31 : : */
32 : : #define SETUP_MAX 8
33 : :
34 : : /*
35 : : * This limit exists to prevent OOMs when the user process stops reading.
36 : : * If usbmon were available to unprivileged processes, it might be open
37 : : * to a local DoS. But we have to keep to root in order to prevent
38 : : * password sniffing from HID devices.
39 : : */
40 : : #define EVENT_MAX (4*PAGE_SIZE / sizeof(struct mon_event_text))
41 : :
42 : : /*
43 : : * Potentially unlimited number; we limit it for similar allocations.
44 : : * The usbfs limits this to 128, but we're not quite as generous.
45 : : */
46 : : #define ISODESC_MAX 5
47 : :
48 : : #define PRINTF_DFL 250 /* with 5 ISOs segs */
49 : :
50 : : struct mon_iso_desc {
51 : : int status;
52 : : unsigned int offset;
53 : : unsigned int length; /* Unsigned here, signed in URB. Historic. */
54 : : };
55 : :
56 : : struct mon_event_text {
57 : : struct list_head e_link;
58 : : int type; /* submit, complete, etc. */
59 : : unsigned long id; /* From pointer, most of the time */
60 : : unsigned int tstamp;
61 : : int busnum;
62 : : char devnum;
63 : : char epnum;
64 : : char is_in;
65 : : char xfertype;
66 : : int length; /* Depends on type: xfer length or act length */
67 : : int status;
68 : : int interval;
69 : : int start_frame;
70 : : int error_count;
71 : : char setup_flag;
72 : : char data_flag;
73 : : int numdesc; /* Full number */
74 : : struct mon_iso_desc isodesc[ISODESC_MAX];
75 : : unsigned char setup[SETUP_MAX];
76 : : unsigned char data[DATA_MAX];
77 : : };
78 : :
79 : : #define SLAB_NAME_SZ 30
80 : : struct mon_reader_text {
81 : : struct kmem_cache *e_slab;
82 : : int nevents;
83 : : struct list_head e_list;
84 : : struct mon_reader r; /* In C, parent class can be placed anywhere */
85 : :
86 : : wait_queue_head_t wait;
87 : : int printf_size;
88 : : size_t printf_offset;
89 : : size_t printf_togo;
90 : : char *printf_buf;
91 : : struct mutex printf_lock;
92 : :
93 : : char slab_name[SLAB_NAME_SZ];
94 : : };
95 : :
96 : : static struct dentry *mon_dir; /* Usually /sys/kernel/debug/usbmon */
97 : :
98 : : static void mon_text_ctor(void *);
99 : :
100 : : struct mon_text_ptr {
101 : : int cnt, limit;
102 : : char *pbuf;
103 : : };
104 : :
105 : : static struct mon_event_text *
106 : : mon_text_read_wait(struct mon_reader_text *rp, struct file *file);
107 : : static void mon_text_read_head_t(struct mon_reader_text *rp,
108 : : struct mon_text_ptr *p, const struct mon_event_text *ep);
109 : : static void mon_text_read_head_u(struct mon_reader_text *rp,
110 : : struct mon_text_ptr *p, const struct mon_event_text *ep);
111 : : static void mon_text_read_statset(struct mon_reader_text *rp,
112 : : struct mon_text_ptr *p, const struct mon_event_text *ep);
113 : : static void mon_text_read_intstat(struct mon_reader_text *rp,
114 : : struct mon_text_ptr *p, const struct mon_event_text *ep);
115 : : static void mon_text_read_isostat(struct mon_reader_text *rp,
116 : : struct mon_text_ptr *p, const struct mon_event_text *ep);
117 : : static void mon_text_read_isodesc(struct mon_reader_text *rp,
118 : : struct mon_text_ptr *p, const struct mon_event_text *ep);
119 : : static void mon_text_read_data(struct mon_reader_text *rp,
120 : : struct mon_text_ptr *p, const struct mon_event_text *ep);
121 : :
122 : : /*
123 : : * mon_text_submit
124 : : * mon_text_complete
125 : : *
126 : : * May be called from an interrupt.
127 : : *
128 : : * This is called with the whole mon_bus locked, so no additional lock.
129 : : */
130 : :
131 : 0 : static inline char mon_text_get_setup(struct mon_event_text *ep,
132 : : struct urb *urb, char ev_type, struct mon_bus *mbus)
133 : : {
134 : :
135 [ # # ]: 0 : if (ep->xfertype != USB_ENDPOINT_XFER_CONTROL || ev_type != 'S')
136 : : return '-';
137 : :
138 [ # # ]: 0 : if (urb->setup_packet == NULL)
139 : : return 'Z'; /* '0' would be not as pretty. */
140 : :
141 : 0 : memcpy(ep->setup, urb->setup_packet, SETUP_MAX);
142 : 0 : return 0;
143 : : }
144 : :
145 : 0 : static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
146 : : int len, char ev_type, struct mon_bus *mbus)
147 : : {
148 : 0 : void *src;
149 : :
150 [ # # ]: 0 : if (len <= 0)
151 : : return 'L';
152 : 0 : if (len >= DATA_MAX)
153 : : len = DATA_MAX;
154 : :
155 [ # # ]: 0 : if (ep->is_in) {
156 [ # # ]: 0 : if (ev_type != 'C')
157 : : return '<';
158 : : } else {
159 [ # # ]: 0 : if (ev_type != 'S')
160 : : return '>';
161 : : }
162 : :
163 [ # # ]: 0 : if (urb->num_sgs == 0) {
164 : 0 : src = urb->transfer_buffer;
165 [ # # ]: 0 : if (src == NULL)
166 : : return 'Z'; /* '0' would be not as pretty. */
167 : : } else {
168 : 0 : struct scatterlist *sg = urb->sg;
169 : :
170 : 0 : if (PageHighMem(sg_page(sg)))
171 : : return 'D';
172 : :
173 : : /* For the text interface we copy only the first sg buffer */
174 : 0 : len = min_t(int, sg->length, len);
175 : 0 : src = sg_virt(sg);
176 : : }
177 : :
178 : 0 : memcpy(ep->data, src, len);
179 : 0 : return 0;
180 : : }
181 : :
182 : 0 : static inline unsigned int mon_get_timestamp(void)
183 : : {
184 : 0 : struct timespec64 now;
185 : 0 : unsigned int stamp;
186 : :
187 : 0 : ktime_get_ts64(&now);
188 : 0 : stamp = now.tv_sec & 0xFFF; /* 2^32 = 4294967296. Limit to 4096s. */
189 : 0 : stamp = stamp * USEC_PER_SEC + now.tv_nsec / NSEC_PER_USEC;
190 : 0 : return stamp;
191 : : }
192 : :
193 : 0 : static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
194 : : char ev_type, int status)
195 : : {
196 : 0 : struct mon_event_text *ep;
197 : 0 : unsigned int stamp;
198 : 0 : struct usb_iso_packet_descriptor *fp;
199 : 0 : struct mon_iso_desc *dp;
200 : 0 : int i, ndesc;
201 : :
202 : 0 : stamp = mon_get_timestamp();
203 : :
204 [ # # # # ]: 0 : if (rp->nevents >= EVENT_MAX ||
205 : 0 : (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) {
206 : 0 : rp->r.m_bus->cnt_text_lost++;
207 : 0 : return;
208 : : }
209 : :
210 : 0 : ep->type = ev_type;
211 : 0 : ep->id = (unsigned long) urb;
212 : 0 : ep->busnum = urb->dev->bus->busnum;
213 : 0 : ep->devnum = urb->dev->devnum;
214 [ # # ]: 0 : ep->epnum = usb_endpoint_num(&urb->ep->desc);
215 [ # # ]: 0 : ep->xfertype = usb_endpoint_type(&urb->ep->desc);
216 [ # # ]: 0 : ep->is_in = usb_urb_dir_in(urb);
217 : 0 : ep->tstamp = stamp;
218 : 0 : ep->length = (ev_type == 'S') ?
219 [ # # ]: 0 : urb->transfer_buffer_length : urb->actual_length;
220 : : /* Collecting status makes debugging sense for submits, too */
221 : 0 : ep->status = status;
222 : :
223 [ # # ]: 0 : if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
224 : 0 : ep->interval = urb->interval;
225 [ # # ]: 0 : } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) {
226 : 0 : ep->interval = urb->interval;
227 : 0 : ep->start_frame = urb->start_frame;
228 : 0 : ep->error_count = urb->error_count;
229 : : }
230 : 0 : ep->numdesc = urb->number_of_packets;
231 [ # # # # ]: 0 : if (ep->xfertype == USB_ENDPOINT_XFER_ISOC &&
232 : : urb->number_of_packets > 0) {
233 : 0 : if ((ndesc = urb->number_of_packets) > ISODESC_MAX)
234 : : ndesc = ISODESC_MAX;
235 : 0 : fp = urb->iso_frame_desc;
236 : 0 : dp = ep->isodesc;
237 [ # # ]: 0 : for (i = 0; i < ndesc; i++) {
238 : 0 : dp->status = fp->status;
239 : 0 : dp->offset = fp->offset;
240 : 0 : dp->length = (ev_type == 'S') ?
241 [ # # ]: 0 : fp->length : fp->actual_length;
242 : 0 : fp++;
243 : 0 : dp++;
244 : : }
245 : : /* Wasteful, but simple to understand: ISO 'C' is sparse. */
246 [ # # ]: 0 : if (ev_type == 'C')
247 : 0 : ep->length = urb->transfer_buffer_length;
248 : : }
249 : :
250 [ # # ]: 0 : ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
251 : 0 : ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
252 : : rp->r.m_bus);
253 : :
254 : 0 : rp->nevents++;
255 : 0 : list_add_tail(&ep->e_link, &rp->e_list);
256 : 0 : wake_up(&rp->wait);
257 : : }
258 : :
259 : 0 : static void mon_text_submit(void *data, struct urb *urb)
260 : : {
261 : 0 : struct mon_reader_text *rp = data;
262 : 0 : mon_text_event(rp, urb, 'S', -EINPROGRESS);
263 : 0 : }
264 : :
265 : 0 : static void mon_text_complete(void *data, struct urb *urb, int status)
266 : : {
267 : 0 : struct mon_reader_text *rp = data;
268 : 0 : mon_text_event(rp, urb, 'C', status);
269 : 0 : }
270 : :
271 : 0 : static void mon_text_error(void *data, struct urb *urb, int error)
272 : : {
273 : 0 : struct mon_reader_text *rp = data;
274 : 0 : struct mon_event_text *ep;
275 : :
276 [ # # # # ]: 0 : if (rp->nevents >= EVENT_MAX ||
277 : 0 : (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) {
278 : 0 : rp->r.m_bus->cnt_text_lost++;
279 : 0 : return;
280 : : }
281 : :
282 : 0 : ep->type = 'E';
283 : 0 : ep->id = (unsigned long) urb;
284 : 0 : ep->busnum = urb->dev->bus->busnum;
285 : 0 : ep->devnum = urb->dev->devnum;
286 : 0 : ep->epnum = usb_endpoint_num(&urb->ep->desc);
287 : 0 : ep->xfertype = usb_endpoint_type(&urb->ep->desc);
288 : 0 : ep->is_in = usb_urb_dir_in(urb);
289 : 0 : ep->tstamp = mon_get_timestamp();
290 : 0 : ep->length = 0;
291 : 0 : ep->status = error;
292 : :
293 : 0 : ep->setup_flag = '-';
294 : 0 : ep->data_flag = 'E';
295 : :
296 : 0 : rp->nevents++;
297 : 0 : list_add_tail(&ep->e_link, &rp->e_list);
298 : 0 : wake_up(&rp->wait);
299 : : }
300 : :
301 : : /*
302 : : * Fetch next event from the circular buffer.
303 : : */
304 : 0 : static struct mon_event_text *mon_text_fetch(struct mon_reader_text *rp,
305 : : struct mon_bus *mbus)
306 : : {
307 : 0 : struct list_head *p;
308 : 0 : unsigned long flags;
309 : :
310 : 0 : spin_lock_irqsave(&mbus->lock, flags);
311 [ # # ]: 0 : if (list_empty(&rp->e_list)) {
312 : 0 : spin_unlock_irqrestore(&mbus->lock, flags);
313 : 0 : return NULL;
314 : : }
315 : 0 : p = rp->e_list.next;
316 : 0 : list_del(p);
317 : 0 : --rp->nevents;
318 : 0 : spin_unlock_irqrestore(&mbus->lock, flags);
319 : 0 : return list_entry(p, struct mon_event_text, e_link);
320 : : }
321 : :
322 : : /*
323 : : */
324 : 0 : static int mon_text_open(struct inode *inode, struct file *file)
325 : : {
326 : 0 : struct mon_bus *mbus;
327 : 0 : struct mon_reader_text *rp;
328 : 0 : int rc;
329 : :
330 : 0 : mutex_lock(&mon_lock);
331 : 0 : mbus = inode->i_private;
332 : :
333 : 0 : rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
334 [ # # ]: 0 : if (rp == NULL) {
335 : 0 : rc = -ENOMEM;
336 : 0 : goto err_alloc;
337 : : }
338 : 0 : INIT_LIST_HEAD(&rp->e_list);
339 : 0 : init_waitqueue_head(&rp->wait);
340 : 0 : mutex_init(&rp->printf_lock);
341 : :
342 : 0 : rp->printf_size = PRINTF_DFL;
343 : 0 : rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL);
344 [ # # ]: 0 : if (rp->printf_buf == NULL) {
345 : 0 : rc = -ENOMEM;
346 : 0 : goto err_alloc_pr;
347 : : }
348 : :
349 : 0 : rp->r.m_bus = mbus;
350 : 0 : rp->r.r_data = rp;
351 : 0 : rp->r.rnf_submit = mon_text_submit;
352 : 0 : rp->r.rnf_error = mon_text_error;
353 : 0 : rp->r.rnf_complete = mon_text_complete;
354 : :
355 : 0 : snprintf(rp->slab_name, SLAB_NAME_SZ, "mon_text_%p", rp);
356 : 0 : rp->e_slab = kmem_cache_create(rp->slab_name,
357 : : sizeof(struct mon_event_text), sizeof(long), 0,
358 : : mon_text_ctor);
359 [ # # ]: 0 : if (rp->e_slab == NULL) {
360 : 0 : rc = -ENOMEM;
361 : 0 : goto err_slab;
362 : : }
363 : :
364 : 0 : mon_reader_add(mbus, &rp->r);
365 : :
366 : 0 : file->private_data = rp;
367 : 0 : mutex_unlock(&mon_lock);
368 : 0 : return 0;
369 : :
370 : : // err_busy:
371 : : // kmem_cache_destroy(rp->e_slab);
372 : : err_slab:
373 : 0 : kfree(rp->printf_buf);
374 : 0 : err_alloc_pr:
375 : 0 : kfree(rp);
376 : 0 : err_alloc:
377 : 0 : mutex_unlock(&mon_lock);
378 : 0 : return rc;
379 : : }
380 : :
381 : 0 : static ssize_t mon_text_copy_to_user(struct mon_reader_text *rp,
382 : : char __user * const buf, const size_t nbytes)
383 : : {
384 : 0 : const size_t togo = min(nbytes, rp->printf_togo);
385 : :
386 [ # # # # ]: 0 : if (copy_to_user(buf, &rp->printf_buf[rp->printf_offset], togo))
387 : : return -EFAULT;
388 : 0 : rp->printf_togo -= togo;
389 : 0 : rp->printf_offset += togo;
390 : 0 : return togo;
391 : : }
392 : :
393 : : /* ppos is not advanced since the llseek operation is not permitted. */
394 : 0 : static ssize_t mon_text_read_t(struct file *file, char __user *buf,
395 : : size_t nbytes, loff_t *ppos)
396 : : {
397 : 0 : struct mon_reader_text *rp = file->private_data;
398 : 0 : struct mon_event_text *ep;
399 : 0 : struct mon_text_ptr ptr;
400 : 0 : ssize_t ret;
401 : :
402 : 0 : mutex_lock(&rp->printf_lock);
403 : :
404 [ # # ]: 0 : if (rp->printf_togo == 0) {
405 : :
406 : 0 : ep = mon_text_read_wait(rp, file);
407 [ # # ]: 0 : if (IS_ERR(ep)) {
408 : 0 : mutex_unlock(&rp->printf_lock);
409 : 0 : return PTR_ERR(ep);
410 : : }
411 : 0 : ptr.cnt = 0;
412 : 0 : ptr.pbuf = rp->printf_buf;
413 : 0 : ptr.limit = rp->printf_size;
414 : :
415 : 0 : mon_text_read_head_t(rp, &ptr, ep);
416 : 0 : mon_text_read_statset(rp, &ptr, ep);
417 : 0 : ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
418 : : " %d", ep->length);
419 : 0 : mon_text_read_data(rp, &ptr, ep);
420 : :
421 : 0 : rp->printf_togo = ptr.cnt;
422 : 0 : rp->printf_offset = 0;
423 : :
424 : 0 : kmem_cache_free(rp->e_slab, ep);
425 : : }
426 : :
427 : 0 : ret = mon_text_copy_to_user(rp, buf, nbytes);
428 : 0 : mutex_unlock(&rp->printf_lock);
429 : 0 : return ret;
430 : : }
431 : :
432 : : /* ppos is not advanced since the llseek operation is not permitted. */
433 : 0 : static ssize_t mon_text_read_u(struct file *file, char __user *buf,
434 : : size_t nbytes, loff_t *ppos)
435 : : {
436 : 0 : struct mon_reader_text *rp = file->private_data;
437 : 0 : struct mon_event_text *ep;
438 : 0 : struct mon_text_ptr ptr;
439 : 0 : ssize_t ret;
440 : :
441 : 0 : mutex_lock(&rp->printf_lock);
442 : :
443 [ # # ]: 0 : if (rp->printf_togo == 0) {
444 : :
445 : 0 : ep = mon_text_read_wait(rp, file);
446 [ # # ]: 0 : if (IS_ERR(ep)) {
447 : 0 : mutex_unlock(&rp->printf_lock);
448 : 0 : return PTR_ERR(ep);
449 : : }
450 : 0 : ptr.cnt = 0;
451 : 0 : ptr.pbuf = rp->printf_buf;
452 : 0 : ptr.limit = rp->printf_size;
453 : :
454 : 0 : mon_text_read_head_u(rp, &ptr, ep);
455 [ # # ]: 0 : if (ep->type == 'E') {
456 : 0 : mon_text_read_statset(rp, &ptr, ep);
457 [ # # ]: 0 : } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) {
458 : 0 : mon_text_read_isostat(rp, &ptr, ep);
459 : 0 : mon_text_read_isodesc(rp, &ptr, ep);
460 [ # # ]: 0 : } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
461 : 0 : mon_text_read_intstat(rp, &ptr, ep);
462 : : } else {
463 : 0 : mon_text_read_statset(rp, &ptr, ep);
464 : : }
465 : 0 : ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
466 : : " %d", ep->length);
467 : 0 : mon_text_read_data(rp, &ptr, ep);
468 : :
469 : 0 : rp->printf_togo = ptr.cnt;
470 : 0 : rp->printf_offset = 0;
471 : :
472 : 0 : kmem_cache_free(rp->e_slab, ep);
473 : : }
474 : :
475 : 0 : ret = mon_text_copy_to_user(rp, buf, nbytes);
476 : 0 : mutex_unlock(&rp->printf_lock);
477 : 0 : return ret;
478 : : }
479 : :
480 : : static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp,
481 : : struct file *file)
482 : : {
483 : : struct mon_bus *mbus = rp->r.m_bus;
484 : : DECLARE_WAITQUEUE(waita, current);
485 : : struct mon_event_text *ep;
486 : :
487 : : add_wait_queue(&rp->wait, &waita);
488 : : set_current_state(TASK_INTERRUPTIBLE);
489 : : while ((ep = mon_text_fetch(rp, mbus)) == NULL) {
490 : : if (file->f_flags & O_NONBLOCK) {
491 : : set_current_state(TASK_RUNNING);
492 : : remove_wait_queue(&rp->wait, &waita);
493 : : return ERR_PTR(-EWOULDBLOCK);
494 : : }
495 : : /*
496 : : * We do not count nwaiters, because ->release is supposed
497 : : * to be called when all openers are gone only.
498 : : */
499 : : schedule();
500 : : if (signal_pending(current)) {
501 : : remove_wait_queue(&rp->wait, &waita);
502 : : return ERR_PTR(-EINTR);
503 : : }
504 : : set_current_state(TASK_INTERRUPTIBLE);
505 : : }
506 : : set_current_state(TASK_RUNNING);
507 : : remove_wait_queue(&rp->wait, &waita);
508 : : return ep;
509 : : }
510 : :
511 : : static void mon_text_read_head_t(struct mon_reader_text *rp,
512 : : struct mon_text_ptr *p, const struct mon_event_text *ep)
513 : : {
514 : : char udir, utype;
515 : :
516 : : udir = (ep->is_in ? 'i' : 'o');
517 : : switch (ep->xfertype) {
518 : : case USB_ENDPOINT_XFER_ISOC: utype = 'Z'; break;
519 : : case USB_ENDPOINT_XFER_INT: utype = 'I'; break;
520 : : case USB_ENDPOINT_XFER_CONTROL: utype = 'C'; break;
521 : : default: /* PIPE_BULK */ utype = 'B';
522 : : }
523 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
524 : : "%lx %u %c %c%c:%03u:%02u",
525 : : ep->id, ep->tstamp, ep->type,
526 : : utype, udir, ep->devnum, ep->epnum);
527 : : }
528 : :
529 : : static void mon_text_read_head_u(struct mon_reader_text *rp,
530 : : struct mon_text_ptr *p, const struct mon_event_text *ep)
531 : : {
532 : : char udir, utype;
533 : :
534 : : udir = (ep->is_in ? 'i' : 'o');
535 : : switch (ep->xfertype) {
536 : : case USB_ENDPOINT_XFER_ISOC: utype = 'Z'; break;
537 : : case USB_ENDPOINT_XFER_INT: utype = 'I'; break;
538 : : case USB_ENDPOINT_XFER_CONTROL: utype = 'C'; break;
539 : : default: /* PIPE_BULK */ utype = 'B';
540 : : }
541 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
542 : : "%lx %u %c %c%c:%d:%03u:%u",
543 : : ep->id, ep->tstamp, ep->type,
544 : : utype, udir, ep->busnum, ep->devnum, ep->epnum);
545 : : }
546 : :
547 : : static void mon_text_read_statset(struct mon_reader_text *rp,
548 : : struct mon_text_ptr *p, const struct mon_event_text *ep)
549 : : {
550 : :
551 : : if (ep->setup_flag == 0) { /* Setup packet is present and captured */
552 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
553 : : " s %02x %02x %04x %04x %04x",
554 : : ep->setup[0],
555 : : ep->setup[1],
556 : : (ep->setup[3] << 8) | ep->setup[2],
557 : : (ep->setup[5] << 8) | ep->setup[4],
558 : : (ep->setup[7] << 8) | ep->setup[6]);
559 : : } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */
560 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
561 : : " %c __ __ ____ ____ ____", ep->setup_flag);
562 : : } else { /* No setup for this kind of URB */
563 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
564 : : " %d", ep->status);
565 : : }
566 : : }
567 : :
568 : : static void mon_text_read_intstat(struct mon_reader_text *rp,
569 : : struct mon_text_ptr *p, const struct mon_event_text *ep)
570 : : {
571 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
572 : : " %d:%d", ep->status, ep->interval);
573 : : }
574 : :
575 : : static void mon_text_read_isostat(struct mon_reader_text *rp,
576 : : struct mon_text_ptr *p, const struct mon_event_text *ep)
577 : : {
578 : : if (ep->type == 'S') {
579 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
580 : : " %d:%d:%d", ep->status, ep->interval, ep->start_frame);
581 : : } else {
582 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
583 : : " %d:%d:%d:%d",
584 : : ep->status, ep->interval, ep->start_frame, ep->error_count);
585 : : }
586 : : }
587 : :
588 : : static void mon_text_read_isodesc(struct mon_reader_text *rp,
589 : : struct mon_text_ptr *p, const struct mon_event_text *ep)
590 : : {
591 : : int ndesc; /* Display this many */
592 : : int i;
593 : : const struct mon_iso_desc *dp;
594 : :
595 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
596 : : " %d", ep->numdesc);
597 : : ndesc = ep->numdesc;
598 : : if (ndesc > ISODESC_MAX)
599 : : ndesc = ISODESC_MAX;
600 : : if (ndesc < 0)
601 : : ndesc = 0;
602 : : dp = ep->isodesc;
603 : : for (i = 0; i < ndesc; i++) {
604 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
605 : : " %d:%u:%u", dp->status, dp->offset, dp->length);
606 : : dp++;
607 : : }
608 : : }
609 : :
610 : : static void mon_text_read_data(struct mon_reader_text *rp,
611 : : struct mon_text_ptr *p, const struct mon_event_text *ep)
612 : : {
613 : : int data_len, i;
614 : :
615 : : if ((data_len = ep->length) > 0) {
616 : : if (ep->data_flag == 0) {
617 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
618 : : " =");
619 : : if (data_len >= DATA_MAX)
620 : : data_len = DATA_MAX;
621 : : for (i = 0; i < data_len; i++) {
622 : : if (i % 4 == 0) {
623 : : p->cnt += snprintf(p->pbuf + p->cnt,
624 : : p->limit - p->cnt,
625 : : " ");
626 : : }
627 : : p->cnt += snprintf(p->pbuf + p->cnt,
628 : : p->limit - p->cnt,
629 : : "%02x", ep->data[i]);
630 : : }
631 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
632 : : "\n");
633 : : } else {
634 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
635 : : " %c\n", ep->data_flag);
636 : : }
637 : : } else {
638 : : p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "\n");
639 : : }
640 : : }
641 : :
642 : 0 : static int mon_text_release(struct inode *inode, struct file *file)
643 : : {
644 : 0 : struct mon_reader_text *rp = file->private_data;
645 : 0 : struct mon_bus *mbus;
646 : : /* unsigned long flags; */
647 : 0 : struct list_head *p;
648 : 0 : struct mon_event_text *ep;
649 : :
650 : 0 : mutex_lock(&mon_lock);
651 : 0 : mbus = inode->i_private;
652 : :
653 [ # # ]: 0 : if (mbus->nreaders <= 0) {
654 : 0 : printk(KERN_ERR TAG ": consistency error on close\n");
655 : 0 : mutex_unlock(&mon_lock);
656 : 0 : return 0;
657 : : }
658 : 0 : mon_reader_del(mbus, &rp->r);
659 : :
660 : : /*
661 : : * In theory, e_list is protected by mbus->lock. However,
662 : : * after mon_reader_del has finished, the following is the case:
663 : : * - we are not on reader list anymore, so new events won't be added;
664 : : * - whole mbus may be dropped if it was orphaned.
665 : : * So, we better not touch mbus.
666 : : */
667 : : /* spin_lock_irqsave(&mbus->lock, flags); */
668 [ # # ]: 0 : while (!list_empty(&rp->e_list)) {
669 : 0 : p = rp->e_list.next;
670 : 0 : ep = list_entry(p, struct mon_event_text, e_link);
671 : 0 : list_del(p);
672 : 0 : --rp->nevents;
673 : 0 : kmem_cache_free(rp->e_slab, ep);
674 : : }
675 : : /* spin_unlock_irqrestore(&mbus->lock, flags); */
676 : :
677 : 0 : kmem_cache_destroy(rp->e_slab);
678 : 0 : kfree(rp->printf_buf);
679 : 0 : kfree(rp);
680 : :
681 : 0 : mutex_unlock(&mon_lock);
682 : 0 : return 0;
683 : : }
684 : :
685 : : static const struct file_operations mon_fops_text_t = {
686 : : .owner = THIS_MODULE,
687 : : .open = mon_text_open,
688 : : .llseek = no_llseek,
689 : : .read = mon_text_read_t,
690 : : .release = mon_text_release,
691 : : };
692 : :
693 : : static const struct file_operations mon_fops_text_u = {
694 : : .owner = THIS_MODULE,
695 : : .open = mon_text_open,
696 : : .llseek = no_llseek,
697 : : .read = mon_text_read_u,
698 : : .release = mon_text_release,
699 : : };
700 : :
701 : 13 : int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
702 : : {
703 : 13 : enum { NAMESZ = 10 };
704 : 13 : char name[NAMESZ];
705 [ - + ]: 13 : int busnum = ubus? ubus->busnum: 0;
706 : 13 : int rc;
707 : :
708 [ + - ]: 13 : if (mon_dir == NULL)
709 : : return 0;
710 : :
711 [ - + ]: 13 : if (ubus != NULL) {
712 : 0 : rc = snprintf(name, NAMESZ, "%dt", busnum);
713 [ # # ]: 0 : if (rc <= 0 || rc >= NAMESZ)
714 : 0 : goto err_print_t;
715 : 0 : mbus->dent_t = debugfs_create_file(name, 0600, mon_dir, mbus,
716 : : &mon_fops_text_t);
717 : : }
718 : :
719 : 13 : rc = snprintf(name, NAMESZ, "%du", busnum);
720 [ - + ]: 13 : if (rc <= 0 || rc >= NAMESZ)
721 : 0 : goto err_print_u;
722 : 13 : mbus->dent_u = debugfs_create_file(name, 0600, mon_dir, mbus,
723 : : &mon_fops_text_u);
724 : :
725 : 13 : rc = snprintf(name, NAMESZ, "%ds", busnum);
726 [ - + ]: 13 : if (rc <= 0 || rc >= NAMESZ)
727 : 0 : goto err_print_s;
728 : 13 : mbus->dent_s = debugfs_create_file(name, 0600, mon_dir, mbus,
729 : : &mon_fops_stat);
730 : :
731 : 13 : return 1;
732 : :
733 : : err_print_s:
734 : 0 : debugfs_remove(mbus->dent_u);
735 : 0 : mbus->dent_u = NULL;
736 : 0 : err_print_u:
737 [ # # ]: 0 : if (ubus != NULL) {
738 : 0 : debugfs_remove(mbus->dent_t);
739 : 0 : mbus->dent_t = NULL;
740 : : }
741 : 0 : err_print_t:
742 : : return 0;
743 : : }
744 : :
745 : 0 : void mon_text_del(struct mon_bus *mbus)
746 : : {
747 : 0 : debugfs_remove(mbus->dent_u);
748 : 0 : debugfs_remove(mbus->dent_t);
749 : 0 : debugfs_remove(mbus->dent_s);
750 : 0 : }
751 : :
752 : : /*
753 : : * Slab interface: constructor.
754 : : */
755 : 0 : static void mon_text_ctor(void *mem)
756 : : {
757 : : /*
758 : : * Nothing to initialize. No, really!
759 : : * So, we fill it with garbage to emulate a reused object.
760 : : */
761 : 0 : memset(mem, 0xe5, sizeof(struct mon_event_text));
762 : 0 : }
763 : :
764 : 13 : int __init mon_text_init(void)
765 : : {
766 : 13 : mon_dir = debugfs_create_dir("usbmon", usb_debug_root);
767 : 13 : return 0;
768 : : }
769 : :
770 : 0 : void mon_text_exit(void)
771 : : {
772 : 0 : debugfs_remove(mon_dir);
773 : 0 : }
|