aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/mon/mon_bin.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/mon/mon_bin.c')
-rw-r--r--drivers/usb/mon/mon_bin.c239
1 files changed, 178 insertions, 61 deletions
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index e06810aef2df..f8d9045d668a 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -37,9 +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)
42
40#ifdef CONFIG_COMPAT 43#ifdef CONFIG_COMPAT
41#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)
42#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)
43#endif 47#endif
44 48
45/* 49/*
@@ -91,7 +95,29 @@ struct mon_bin_hdr {
91 int status; 95 int status;
92 unsigned int len_urb; /* Length of data (submitted or actual) */ 96 unsigned int len_urb; /* Length of data (submitted or actual) */
93 unsigned int len_cap; /* Delivered length */ 97 unsigned int len_cap; /* Delivered length */
94 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;
95}; 121};
96 122
97/* per file statistic */ 123/* per file statistic */
@@ -101,7 +127,7 @@ struct mon_bin_stats {
101}; 127};
102 128
103struct mon_bin_get { 129struct mon_bin_get {
104 struct mon_bin_hdr __user *hdr; /* Only 48 bytes, not 64. */ 130 struct mon_bin_hdr __user *hdr; /* Can be 48 bytes or 64. */
105 void __user *data; 131 void __user *data;
106 size_t alloc; /* Length of data (can be zero) */ 132 size_t alloc; /* Length of data (can be zero) */
107}; 133};
@@ -130,6 +156,11 @@ struct mon_bin_mfetch32 {
130#define PKT_ALIGN 64 156#define PKT_ALIGN 64
131#define PKT_SIZE 64 157#define PKT_SIZE 64
132 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
133/* max number of USB bus supported */ 164/* max number of USB bus supported */
134#define MON_BIN_MAX_MINOR 128 165#define MON_BIN_MAX_MINOR 128
135 166
@@ -359,12 +390,8 @@ static inline char mon_bin_get_setup(unsigned char *setupb,
359 const struct urb *urb, char ev_type) 390 const struct urb *urb, char ev_type)
360{ 391{
361 392
362 if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S')
363 return '-';
364
365 if (urb->setup_packet == NULL) 393 if (urb->setup_packet == NULL)
366 return 'Z'; 394 return 'Z';
367
368 memcpy(setupb, urb->setup_packet, SETUP_LEN); 395 memcpy(setupb, urb->setup_packet, SETUP_LEN);
369 return 0; 396 return 0;
370} 397}
@@ -386,6 +413,26 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp,
386 return 0; 413 return 0;
387} 414}
388 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
389static 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,
390 char ev_type, int status) 437 char ev_type, int status)
391{ 438{
@@ -395,6 +442,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
395 unsigned int urb_length; 442 unsigned int urb_length;
396 unsigned int offset; 443 unsigned int offset;
397 unsigned int length; 444 unsigned int length;
445 unsigned int ndesc, lendesc;
398 unsigned char dir; 446 unsigned char dir;
399 struct mon_bin_hdr *ep; 447 struct mon_bin_hdr *ep;
400 char data_tag = 0; 448 char data_tag = 0;
@@ -406,6 +454,19 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
406 /* 454 /*
407 * Find the maximum allowable length, then allocate space. 455 * Find the maximum allowable length, then allocate space.
408 */ 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
409 urb_length = (ev_type == 'S') ? 470 urb_length = (ev_type == 'S') ?
410 urb->transfer_buffer_length : urb->actual_length; 471 urb->transfer_buffer_length : urb->actual_length;
411 length = urb_length; 472 length = urb_length;
@@ -428,10 +489,12 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
428 dir = 0; 489 dir = 0;
429 } 490 }
430 491
431 if (rp->mmap_active) 492 if (rp->mmap_active) {
432 offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE); 493 offset = mon_buff_area_alloc_contiguous(rp,
433 else 494 length + PKT_SIZE + lendesc);
434 offset = mon_buff_area_alloc(rp, length + PKT_SIZE); 495 } else {
496 offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc);
497 }
435 if (offset == ~0) { 498 if (offset == ~0) {
436 rp->cnt_lost++; 499 rp->cnt_lost++;
437 spin_unlock_irqrestore(&rp->b_lock, flags); 500 spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -455,9 +518,31 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
455 ep->ts_usec = ts.tv_usec; 518 ep->ts_usec = ts.tv_usec;
456 ep->status = status; 519 ep->status = status;
457 ep->len_urb = urb_length; 520 ep->len_urb = urb_length;
458 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 }
459 545
460 ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type);
461 if (length != 0) { 546 if (length != 0) {
462 ep->flag_data = mon_bin_get_data(rp, offset, urb, length); 547 ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
463 if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ 548 if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */
@@ -591,7 +676,8 @@ err_alloc:
591 * Returns zero or error. 676 * Returns zero or error.
592 */ 677 */
593static 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,
594 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)
595{ 681{
596 unsigned long flags; 682 unsigned long flags;
597 struct mon_bin_hdr *ep; 683 struct mon_bin_hdr *ep;
@@ -608,7 +694,7 @@ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
608 694
609 ep = MON_OFF2HDR(rp, rp->b_out); 695 ep = MON_OFF2HDR(rp, rp->b_out);
610 696
611 if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) { 697 if (copy_to_user(hdr, ep, hdrbytes)) {
612 mutex_unlock(&rp->fetch_lock); 698 mutex_unlock(&rp->fetch_lock);
613 return -EFAULT; 699 return -EFAULT;
614 } 700 }
@@ -656,6 +742,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
656 size_t nbytes, loff_t *ppos) 742 size_t nbytes, loff_t *ppos)
657{ 743{
658 struct mon_reader_bin *rp = file->private_data; 744 struct mon_reader_bin *rp = file->private_data;
745 unsigned int hdrbytes = PKT_SZ_API0;
659 unsigned long flags; 746 unsigned long flags;
660 struct mon_bin_hdr *ep; 747 struct mon_bin_hdr *ep;
661 unsigned int offset; 748 unsigned int offset;
@@ -673,8 +760,8 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
673 760
674 ep = MON_OFF2HDR(rp, rp->b_out); 761 ep = MON_OFF2HDR(rp, rp->b_out);
675 762
676 if (rp->b_read < sizeof(struct mon_bin_hdr)) { 763 if (rp->b_read < hdrbytes) {
677 step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read); 764 step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
678 ptr = ((char *)ep) + rp->b_read; 765 ptr = ((char *)ep) + rp->b_read;
679 if (step_len && copy_to_user(buf, ptr, step_len)) { 766 if (step_len && copy_to_user(buf, ptr, step_len)) {
680 mutex_unlock(&rp->fetch_lock); 767 mutex_unlock(&rp->fetch_lock);
@@ -686,13 +773,13 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
686 done += step_len; 773 done += step_len;
687 } 774 }
688 775
689 if (rp->b_read >= sizeof(struct mon_bin_hdr)) { 776 if (rp->b_read >= hdrbytes) {
690 step_len = ep->len_cap; 777 step_len = ep->len_cap;
691 step_len -= rp->b_read - sizeof(struct mon_bin_hdr); 778 step_len -= rp->b_read - hdrbytes;
692 if (step_len > nbytes) 779 if (step_len > nbytes)
693 step_len = nbytes; 780 step_len = nbytes;
694 offset = rp->b_out + PKT_SIZE; 781 offset = rp->b_out + PKT_SIZE;
695 offset += rp->b_read - sizeof(struct mon_bin_hdr); 782 offset += rp->b_read - hdrbytes;
696 if (offset >= rp->b_size) 783 if (offset >= rp->b_size)
697 offset -= rp->b_size; 784 offset -= rp->b_size;
698 if (copy_from_buf(rp, offset, buf, step_len)) { 785 if (copy_from_buf(rp, offset, buf, step_len)) {
@@ -708,7 +795,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
708 /* 795 /*
709 * 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.
710 */ 797 */
711 if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) { 798 if (rp->b_read >= hdrbytes + ep->len_cap) {
712 spin_lock_irqsave(&rp->b_lock, flags); 799 spin_lock_irqsave(&rp->b_lock, flags);
713 mon_buff_area_free(rp, PKT_SIZE + ep->len_cap); 800 mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
714 spin_unlock_irqrestore(&rp->b_lock, flags); 801 spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -907,6 +994,7 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
907 break; 994 break;
908 995
909 case MON_IOCX_GET: 996 case MON_IOCX_GET:
997 case MON_IOCX_GETX:
910 { 998 {
911 struct mon_bin_get getb; 999 struct mon_bin_get getb;
912 1000
@@ -916,26 +1004,12 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
916 1004
917 if (getb.alloc > 0x10000000) /* Want to cast to u32 */ 1005 if (getb.alloc > 0x10000000) /* Want to cast to u32 */
918 return -EINVAL; 1006 return -EINVAL;
919 ret = mon_bin_get_event(file, rp, 1007 ret = mon_bin_get_event(file, rp, getb.hdr,
920 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);
921 } 1010 }
922 break; 1011 break;
923 1012
924#ifdef CONFIG_COMPAT
925 case MON_IOCX_GET32: {
926 struct mon_bin_get32 getb;
927
928 if (copy_from_user(&getb, (void __user *)arg,
929 sizeof(struct mon_bin_get32)))
930 return -EFAULT;
931
932 ret = mon_bin_get_event(file, rp,
933 compat_ptr(getb.hdr32), compat_ptr(getb.data32),
934 getb.alloc32);
935 }
936 break;
937#endif
938
939 case MON_IOCX_MFETCH: 1013 case MON_IOCX_MFETCH:
940 { 1014 {
941 struct mon_bin_mfetch mfetch; 1015 struct mon_bin_mfetch mfetch;
@@ -962,7 +1036,59 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
962 } 1036 }
963 break; 1037 break;
964 1038
1039 case MON_IOCG_STATS: {
1040 struct mon_bin_stats __user *sp;
1041 unsigned int nevents;
1042 unsigned int ndropped;
1043
1044 spin_lock_irqsave(&rp->b_lock, flags);
1045 ndropped = rp->cnt_lost;
1046 rp->cnt_lost = 0;
1047 spin_unlock_irqrestore(&rp->b_lock, flags);
1048 nevents = mon_bin_queued(rp);
1049
1050 sp = (struct mon_bin_stats __user *)arg;
1051 if (put_user(rp->cnt_lost, &sp->dropped))
1052 return -EFAULT;
1053 if (put_user(nevents, &sp->queued))
1054 return -EFAULT;
1055
1056 }
1057 break;
1058
1059 default:
1060 return -ENOTTY;
1061 }
1062
1063 return ret;
1064}
1065
965#ifdef CONFIG_COMPAT 1066#ifdef CONFIG_COMPAT
1067static long mon_bin_compat_ioctl(struct file *file,
1068 unsigned int cmd, unsigned long arg)
1069{
1070 struct mon_reader_bin *rp = file->private_data;
1071 int ret;
1072
1073 switch (cmd) {
1074
1075 case MON_IOCX_GET32:
1076 case MON_IOCX_GETX32:
1077 {
1078 struct mon_bin_get32 getb;
1079
1080 if (copy_from_user(&getb, (void __user *)arg,
1081 sizeof(struct mon_bin_get32)))
1082 return -EFAULT;
1083
1084 ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32),
1085 (cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1,
1086 compat_ptr(getb.data32), getb.alloc32);
1087 if (ret < 0)
1088 return ret;
1089 }
1090 return 0;
1091
966 case MON_IOCX_MFETCH32: 1092 case MON_IOCX_MFETCH32:
967 { 1093 {
968 struct mon_bin_mfetch32 mfetch; 1094 struct mon_bin_mfetch32 mfetch;
@@ -986,37 +1112,25 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
986 return ret; 1112 return ret;
987 if (put_user(ret, &uptr->nfetch32)) 1113 if (put_user(ret, &uptr->nfetch32))
988 return -EFAULT; 1114 return -EFAULT;
989 ret = 0;
990 } 1115 }
991 break; 1116 return 0;
992#endif
993
994 case MON_IOCG_STATS: {
995 struct mon_bin_stats __user *sp;
996 unsigned int nevents;
997 unsigned int ndropped;
998
999 spin_lock_irqsave(&rp->b_lock, flags);
1000 ndropped = rp->cnt_lost;
1001 rp->cnt_lost = 0;
1002 spin_unlock_irqrestore(&rp->b_lock, flags);
1003 nevents = mon_bin_queued(rp);
1004 1117
1005 sp = (struct mon_bin_stats __user *)arg; 1118 case MON_IOCG_STATS:
1006 if (put_user(rp->cnt_lost, &sp->dropped)) 1119 return mon_bin_ioctl(NULL, file, cmd,
1007 return -EFAULT; 1120 (unsigned long) compat_ptr(arg));
1008 if (put_user(nevents, &sp->queued))
1009 return -EFAULT;
1010 1121
1011 } 1122 case MON_IOCQ_URB_LEN:
1012 break; 1123 case MON_IOCQ_RING_SIZE:
1124 case MON_IOCT_RING_SIZE:
1125 case MON_IOCH_MFLUSH:
1126 return mon_bin_ioctl(NULL, file, cmd, arg);
1013 1127
1014 default: 1128 default:
1015 return -ENOTTY; 1129 ;
1016 } 1130 }
1017 1131 return -ENOTTY;
1018 return ret;
1019} 1132}
1133#endif /* CONFIG_COMPAT */
1020 1134
1021static unsigned int 1135static unsigned int
1022mon_bin_poll(struct file *file, struct poll_table_struct *wait) 1136mon_bin_poll(struct file *file, struct poll_table_struct *wait)
@@ -1094,6 +1208,9 @@ static const struct file_operations mon_fops_binary = {
1094 /* .write = mon_text_write, */ 1208 /* .write = mon_text_write, */
1095 .poll = mon_bin_poll, 1209 .poll = mon_bin_poll,
1096 .ioctl = mon_bin_ioctl, 1210 .ioctl = mon_bin_ioctl,
1211#ifdef CONFIG_COMPAT
1212 .compat_ioctl = mon_bin_compat_ioctl,
1213#endif
1097 .release = mon_bin_release, 1214 .release = mon_bin_release,
1098 .mmap = mon_bin_mmap, 1215 .mmap = mon_bin_mmap,
1099}; 1216};