aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/mon
diff options
context:
space:
mode:
authorPete Zaitcev <zaitcev@redhat.com>2009-02-20 00:54:45 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-03-24 19:20:36 -0400
commit471c604daf73ff549d374ee54f9e6bfd5a54d4e8 (patch)
treeab697965b7d4b1e017bfbe274609de6cbfd21b1a /drivers/usb/mon
parent1ded7ea47b8829a06068c3bb5e3ebe471076617a (diff)
USB: usbmon: Add binary API v1
This patch adds an extension to the binary API so it reaches parity with existing text API (so-called "1u"). The extension delivers additional data, such as ISO descriptors and the interrupt interval. Signed-Off-By: Pete Zaitcev <zaitcev@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/mon')
-rw-r--r--drivers/usb/mon/mon_bin.c142
1 files changed, 116 insertions, 26 deletions
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 4cf27c72423e..f8d9045d668a 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -37,10 +37,13 @@
37#define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) 37#define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
38#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) 38#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
39#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) 39#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
40/* #9 was MON_IOCT_SETAPI */
41#define MON_IOCX_GETX _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get)
40 42
41#ifdef CONFIG_COMPAT 43#ifdef CONFIG_COMPAT
42#define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32) 44#define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32)
43#define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32) 45#define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32)
46#define MON_IOCX_GETX32 _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get32)
44#endif 47#endif
45 48
46/* 49/*
@@ -92,7 +95,29 @@ struct mon_bin_hdr {
92 int status; 95 int status;
93 unsigned int len_urb; /* Length of data (submitted or actual) */ 96 unsigned int len_urb; /* Length of data (submitted or actual) */
94 unsigned int len_cap; /* Delivered length */ 97 unsigned int len_cap; /* Delivered length */
95 unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ 98 union {
99 unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
100 struct iso_rec {
101 int error_count;
102 int numdesc;
103 } iso;
104 } s;
105 int interval;
106 int start_frame;
107 unsigned int xfer_flags;
108 unsigned int ndesc; /* Actual number of ISO descriptors */
109};
110
111/*
112 * ISO vector, packed into the head of data stream.
113 * This has to take 16 bytes to make sure that the end of buffer
114 * wrap is not happening in the middle of a descriptor.
115 */
116struct mon_bin_isodesc {
117 int iso_status;
118 unsigned int iso_off;
119 unsigned int iso_len;
120 u32 _pad;
96}; 121};
97 122
98/* per file statistic */ 123/* per file statistic */
@@ -102,7 +127,7 @@ struct mon_bin_stats {
102}; 127};
103 128
104struct mon_bin_get { 129struct mon_bin_get {
105 struct mon_bin_hdr __user *hdr; /* Only 48 bytes, not 64. */ 130 struct mon_bin_hdr __user *hdr; /* Can be 48 bytes or 64. */
106 void __user *data; 131 void __user *data;
107 size_t alloc; /* Length of data (can be zero) */ 132 size_t alloc; /* Length of data (can be zero) */
108}; 133};
@@ -131,6 +156,11 @@ struct mon_bin_mfetch32 {
131#define PKT_ALIGN 64 156#define PKT_ALIGN 64
132#define PKT_SIZE 64 157#define PKT_SIZE 64
133 158
159#define PKT_SZ_API0 48 /* API 0 (2.6.20) size */
160#define PKT_SZ_API1 64 /* API 1 size: extra fields */
161
162#define ISODESC_MAX 128 /* Same number as usbfs allows, 2048 bytes. */
163
134/* max number of USB bus supported */ 164/* max number of USB bus supported */
135#define MON_BIN_MAX_MINOR 128 165#define MON_BIN_MAX_MINOR 128
136 166
@@ -360,12 +390,8 @@ static inline char mon_bin_get_setup(unsigned char *setupb,
360 const struct urb *urb, char ev_type) 390 const struct urb *urb, char ev_type)
361{ 391{
362 392
363 if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S')
364 return '-';
365
366 if (urb->setup_packet == NULL) 393 if (urb->setup_packet == NULL)
367 return 'Z'; 394 return 'Z';
368
369 memcpy(setupb, urb->setup_packet, SETUP_LEN); 395 memcpy(setupb, urb->setup_packet, SETUP_LEN);
370 return 0; 396 return 0;
371} 397}
@@ -387,6 +413,26 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp,
387 return 0; 413 return 0;
388} 414}
389 415
416static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
417 unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc)
418{
419 struct mon_bin_isodesc *dp;
420 struct usb_iso_packet_descriptor *fp;
421
422 fp = urb->iso_frame_desc;
423 while (ndesc-- != 0) {
424 dp = (struct mon_bin_isodesc *)
425 (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
426 dp->iso_status = fp->status;
427 dp->iso_off = fp->offset;
428 dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length;
429 dp->_pad = 0;
430 if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size)
431 offset = 0;
432 fp++;
433 }
434}
435
390static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, 436static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
391 char ev_type, int status) 437 char ev_type, int status)
392{ 438{
@@ -396,6 +442,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
396 unsigned int urb_length; 442 unsigned int urb_length;
397 unsigned int offset; 443 unsigned int offset;
398 unsigned int length; 444 unsigned int length;
445 unsigned int ndesc, lendesc;
399 unsigned char dir; 446 unsigned char dir;
400 struct mon_bin_hdr *ep; 447 struct mon_bin_hdr *ep;
401 char data_tag = 0; 448 char data_tag = 0;
@@ -407,6 +454,19 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
407 /* 454 /*
408 * Find the maximum allowable length, then allocate space. 455 * Find the maximum allowable length, then allocate space.
409 */ 456 */
457 if (usb_endpoint_xfer_isoc(epd)) {
458 if (urb->number_of_packets < 0) {
459 ndesc = 0;
460 } else if (urb->number_of_packets >= ISODESC_MAX) {
461 ndesc = ISODESC_MAX;
462 } else {
463 ndesc = urb->number_of_packets;
464 }
465 } else {
466 ndesc = 0;
467 }
468 lendesc = ndesc*sizeof(struct mon_bin_isodesc);
469
410 urb_length = (ev_type == 'S') ? 470 urb_length = (ev_type == 'S') ?
411 urb->transfer_buffer_length : urb->actual_length; 471 urb->transfer_buffer_length : urb->actual_length;
412 length = urb_length; 472 length = urb_length;
@@ -429,10 +489,12 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
429 dir = 0; 489 dir = 0;
430 } 490 }
431 491
432 if (rp->mmap_active) 492 if (rp->mmap_active) {
433 offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE); 493 offset = mon_buff_area_alloc_contiguous(rp,
434 else 494 length + PKT_SIZE + lendesc);
435 offset = mon_buff_area_alloc(rp, length + PKT_SIZE); 495 } else {
496 offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc);
497 }
436 if (offset == ~0) { 498 if (offset == ~0) {
437 rp->cnt_lost++; 499 rp->cnt_lost++;
438 spin_unlock_irqrestore(&rp->b_lock, flags); 500 spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -456,9 +518,31 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
456 ep->ts_usec = ts.tv_usec; 518 ep->ts_usec = ts.tv_usec;
457 ep->status = status; 519 ep->status = status;
458 ep->len_urb = urb_length; 520 ep->len_urb = urb_length;
459 ep->len_cap = length; 521 ep->len_cap = length + lendesc;
522 ep->xfer_flags = urb->transfer_flags;
523
524 if (usb_endpoint_xfer_int(epd)) {
525 ep->interval = urb->interval;
526 } else if (usb_endpoint_xfer_isoc(epd)) {
527 ep->interval = urb->interval;
528 ep->start_frame = urb->start_frame;
529 ep->s.iso.error_count = urb->error_count;
530 ep->s.iso.numdesc = urb->number_of_packets;
531 }
532
533 if (usb_endpoint_xfer_control(epd) && ev_type == 'S') {
534 ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type);
535 } else {
536 ep->flag_setup = '-';
537 }
538
539 if (ndesc != 0) {
540 ep->ndesc = ndesc;
541 mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc);
542 if ((offset += lendesc) >= rp->b_size)
543 offset -= rp->b_size;
544 }
460 545
461 ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type);
462 if (length != 0) { 546 if (length != 0) {
463 ep->flag_data = mon_bin_get_data(rp, offset, urb, length); 547 ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
464 if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ 548 if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */
@@ -592,7 +676,8 @@ err_alloc:
592 * Returns zero or error. 676 * Returns zero or error.
593 */ 677 */
594static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp, 678static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
595 struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes) 679 struct mon_bin_hdr __user *hdr, unsigned int hdrbytes,
680 void __user *data, unsigned int nbytes)
596{ 681{
597 unsigned long flags; 682 unsigned long flags;
598 struct mon_bin_hdr *ep; 683 struct mon_bin_hdr *ep;
@@ -609,7 +694,7 @@ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
609 694
610 ep = MON_OFF2HDR(rp, rp->b_out); 695 ep = MON_OFF2HDR(rp, rp->b_out);
611 696
612 if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) { 697 if (copy_to_user(hdr, ep, hdrbytes)) {
613 mutex_unlock(&rp->fetch_lock); 698 mutex_unlock(&rp->fetch_lock);
614 return -EFAULT; 699 return -EFAULT;
615 } 700 }
@@ -657,6 +742,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
657 size_t nbytes, loff_t *ppos) 742 size_t nbytes, loff_t *ppos)
658{ 743{
659 struct mon_reader_bin *rp = file->private_data; 744 struct mon_reader_bin *rp = file->private_data;
745 unsigned int hdrbytes = PKT_SZ_API0;
660 unsigned long flags; 746 unsigned long flags;
661 struct mon_bin_hdr *ep; 747 struct mon_bin_hdr *ep;
662 unsigned int offset; 748 unsigned int offset;
@@ -674,8 +760,8 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
674 760
675 ep = MON_OFF2HDR(rp, rp->b_out); 761 ep = MON_OFF2HDR(rp, rp->b_out);
676 762
677 if (rp->b_read < sizeof(struct mon_bin_hdr)) { 763 if (rp->b_read < hdrbytes) {
678 step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read); 764 step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
679 ptr = ((char *)ep) + rp->b_read; 765 ptr = ((char *)ep) + rp->b_read;
680 if (step_len && copy_to_user(buf, ptr, step_len)) { 766 if (step_len && copy_to_user(buf, ptr, step_len)) {
681 mutex_unlock(&rp->fetch_lock); 767 mutex_unlock(&rp->fetch_lock);
@@ -687,13 +773,13 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
687 done += step_len; 773 done += step_len;
688 } 774 }
689 775
690 if (rp->b_read >= sizeof(struct mon_bin_hdr)) { 776 if (rp->b_read >= hdrbytes) {
691 step_len = ep->len_cap; 777 step_len = ep->len_cap;
692 step_len -= rp->b_read - sizeof(struct mon_bin_hdr); 778 step_len -= rp->b_read - hdrbytes;
693 if (step_len > nbytes) 779 if (step_len > nbytes)
694 step_len = nbytes; 780 step_len = nbytes;
695 offset = rp->b_out + PKT_SIZE; 781 offset = rp->b_out + PKT_SIZE;
696 offset += rp->b_read - sizeof(struct mon_bin_hdr); 782 offset += rp->b_read - hdrbytes;
697 if (offset >= rp->b_size) 783 if (offset >= rp->b_size)
698 offset -= rp->b_size; 784 offset -= rp->b_size;
699 if (copy_from_buf(rp, offset, buf, step_len)) { 785 if (copy_from_buf(rp, offset, buf, step_len)) {
@@ -709,7 +795,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
709 /* 795 /*
710 * Check if whole packet was read, and if so, jump to the next one. 796 * Check if whole packet was read, and if so, jump to the next one.
711 */ 797 */
712 if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) { 798 if (rp->b_read >= hdrbytes + ep->len_cap) {
713 spin_lock_irqsave(&rp->b_lock, flags); 799 spin_lock_irqsave(&rp->b_lock, flags);
714 mon_buff_area_free(rp, PKT_SIZE + ep->len_cap); 800 mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
715 spin_unlock_irqrestore(&rp->b_lock, flags); 801 spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -908,6 +994,7 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
908 break; 994 break;
909 995
910 case MON_IOCX_GET: 996 case MON_IOCX_GET:
997 case MON_IOCX_GETX:
911 { 998 {
912 struct mon_bin_get getb; 999 struct mon_bin_get getb;
913 1000
@@ -917,8 +1004,9 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
917 1004
918 if (getb.alloc > 0x10000000) /* Want to cast to u32 */ 1005 if (getb.alloc > 0x10000000) /* Want to cast to u32 */
919 return -EINVAL; 1006 return -EINVAL;
920 ret = mon_bin_get_event(file, rp, 1007 ret = mon_bin_get_event(file, rp, getb.hdr,
921 getb.hdr, getb.data, (unsigned int)getb.alloc); 1008 (cmd == MON_IOCX_GET)? PKT_SZ_API0: PKT_SZ_API1,
1009 getb.data, (unsigned int)getb.alloc);
922 } 1010 }
923 break; 1011 break;
924 1012
@@ -984,16 +1072,18 @@ static long mon_bin_compat_ioctl(struct file *file,
984 1072
985 switch (cmd) { 1073 switch (cmd) {
986 1074
987 case MON_IOCX_GET32: { 1075 case MON_IOCX_GET32:
1076 case MON_IOCX_GETX32:
1077 {
988 struct mon_bin_get32 getb; 1078 struct mon_bin_get32 getb;
989 1079
990 if (copy_from_user(&getb, (void __user *)arg, 1080 if (copy_from_user(&getb, (void __user *)arg,
991 sizeof(struct mon_bin_get32))) 1081 sizeof(struct mon_bin_get32)))
992 return -EFAULT; 1082 return -EFAULT;
993 1083
994 ret = mon_bin_get_event(file, rp, 1084 ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32),
995 compat_ptr(getb.hdr32), compat_ptr(getb.data32), 1085 (cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1,
996 getb.alloc32); 1086 compat_ptr(getb.data32), getb.alloc32);
997 if (ret < 0) 1087 if (ret < 0)
998 return ret; 1088 return ret;
999 } 1089 }