diff options
author | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-04-21 05:33:03 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-04-21 08:44:55 -0400 |
commit | 64131a87f2aae2ed9e05d8227c5b009ca6c50d98 (patch) | |
tree | fdea23fd59216120bf54a48c60ca24489a733f14 /drivers/usb/gadget/function | |
parent | 676ee36be04985062522804c2de04f0764212be6 (diff) | |
parent | 2c33ce009ca2389dbf0535d0672214d09738e35e (diff) |
Merge branch 'drm-next-merged' of git://people.freedesktop.org/~airlied/linux into v4l_for_linus
* 'drm-next-merged' of git://people.freedesktop.org/~airlied/linux: (9717 commits)
media-bus: Fixup RGB444_1X12, RGB565_1X16, and YUV8_1X24 media bus format
hexdump: avoid warning in test function
fs: take i_mutex during prepare_binprm for set[ug]id executables
smp: Fix error case handling in smp_call_function_*()
iommu-common: Fix PARISC compile-time warnings
sparc: Make LDC use common iommu poll management functions
sparc: Make sparc64 use scalable lib/iommu-common.c functions
Break up monolithic iommu table/lock into finer graularity pools and lock
sparc: Revert generic IOMMU allocator.
tools/power turbostat: correct dumped pkg-cstate-limit value
tools/power turbostat: calculate TSC frequency from CPUID(0x15) on SKL
tools/power turbostat: correct DRAM RAPL units on recent Xeon processors
tools/power turbostat: Initial Skylake support
tools/power turbostat: Use $(CURDIR) instead of $(PWD) and add support for O= option in Makefile
tools/power turbostat: modprobe msr, if needed
tools/power turbostat: dump MSR_TURBO_RATIO_LIMIT2
tools/power turbostat: use new MSR_TURBO_RATIO_LIMIT names
Bluetooth: hidp: Fix regression with older userspace and flags validation
config: Enable NEED_DMA_MAP_STATE by default when SWIOTLB is selected
perf/x86/intel/pt: Fix and clean up error handling in pt_event_add()
...
That solves several merge conflicts:
Documentation/DocBook/media/v4l/subdev-formats.xml
Documentation/devicetree/bindings/vendor-prefixes.txt
drivers/staging/media/mn88473/mn88473.c
include/linux/kconfig.h
include/uapi/linux/media-bus-format.h
The ones at subdev-formats.xml and media-bus-format.h are not trivial.
That's why we opted to merge from DRM.
Diffstat (limited to 'drivers/usb/gadget/function')
-rw-r--r-- | drivers/usb/gadget/function/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 208 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_hid.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_loopback.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_mass_storage.c | 109 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_phonet.c | 5 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_printer.c | 1471 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_sourcesink.c | 511 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_uac2.c | 34 | ||||
-rw-r--r-- | drivers/usb/gadget/function/g_zero.h | 13 | ||||
-rw-r--r-- | drivers/usb/gadget/function/u_printer.h | 37 | ||||
-rw-r--r-- | drivers/usb/gadget/function/u_serial.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_v4l2.c | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_video.c | 1 |
14 files changed, 1672 insertions, 728 deletions
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile index f71b1aaa0edf..bd7def576955 100644 --- a/drivers/usb/gadget/function/Makefile +++ b/drivers/usb/gadget/function/Makefile | |||
@@ -42,3 +42,5 @@ usb_f_midi-y := f_midi.o | |||
42 | obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o | 42 | obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o |
43 | usb_f_hid-y := f_hid.o | 43 | usb_f_hid-y := f_hid.o |
44 | obj-$(CONFIG_USB_F_HID) += usb_f_hid.o | 44 | obj-$(CONFIG_USB_F_HID) += usb_f_hid.o |
45 | usb_f_printer-y := f_printer.o | ||
46 | obj-$(CONFIG_USB_F_PRINTER) += usb_f_printer.o | ||
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index af98b096af2f..6bdb57069044 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
24 | #include <linux/hid.h> | 24 | #include <linux/hid.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/uio.h> | ||
26 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
27 | 28 | ||
28 | #include <linux/usb/composite.h> | 29 | #include <linux/usb/composite.h> |
@@ -144,10 +145,9 @@ struct ffs_io_data { | |||
144 | bool read; | 145 | bool read; |
145 | 146 | ||
146 | struct kiocb *kiocb; | 147 | struct kiocb *kiocb; |
147 | const struct iovec *iovec; | 148 | struct iov_iter data; |
148 | unsigned long nr_segs; | 149 | const void *to_free; |
149 | char __user *buf; | 150 | char *buf; |
150 | size_t len; | ||
151 | 151 | ||
152 | struct mm_struct *mm; | 152 | struct mm_struct *mm; |
153 | struct work_struct work; | 153 | struct work_struct work; |
@@ -649,42 +649,24 @@ static void ffs_user_copy_worker(struct work_struct *work) | |||
649 | io_data->req->actual; | 649 | io_data->req->actual; |
650 | 650 | ||
651 | if (io_data->read && ret > 0) { | 651 | if (io_data->read && ret > 0) { |
652 | int i; | ||
653 | size_t pos = 0; | ||
654 | |||
655 | /* | ||
656 | * Since req->length may be bigger than io_data->len (after | ||
657 | * being rounded up to maxpacketsize), we may end up with more | ||
658 | * data then user space has space for. | ||
659 | */ | ||
660 | ret = min_t(int, ret, io_data->len); | ||
661 | |||
662 | use_mm(io_data->mm); | 652 | use_mm(io_data->mm); |
663 | for (i = 0; i < io_data->nr_segs; i++) { | 653 | ret = copy_to_iter(io_data->buf, ret, &io_data->data); |
664 | size_t len = min_t(size_t, ret - pos, | 654 | if (iov_iter_count(&io_data->data)) |
665 | io_data->iovec[i].iov_len); | 655 | ret = -EFAULT; |
666 | if (!len) | ||
667 | break; | ||
668 | if (unlikely(copy_to_user(io_data->iovec[i].iov_base, | ||
669 | &io_data->buf[pos], len))) { | ||
670 | ret = -EFAULT; | ||
671 | break; | ||
672 | } | ||
673 | pos += len; | ||
674 | } | ||
675 | unuse_mm(io_data->mm); | 656 | unuse_mm(io_data->mm); |
676 | } | 657 | } |
677 | 658 | ||
678 | aio_complete(io_data->kiocb, ret, ret); | 659 | io_data->kiocb->ki_complete(io_data->kiocb, ret, ret); |
679 | 660 | ||
680 | if (io_data->ffs->ffs_eventfd && !io_data->kiocb->ki_eventfd) | 661 | if (io_data->ffs->ffs_eventfd && |
662 | !(io_data->kiocb->ki_flags & IOCB_EVENTFD)) | ||
681 | eventfd_signal(io_data->ffs->ffs_eventfd, 1); | 663 | eventfd_signal(io_data->ffs->ffs_eventfd, 1); |
682 | 664 | ||
683 | usb_ep_free_request(io_data->ep, io_data->req); | 665 | usb_ep_free_request(io_data->ep, io_data->req); |
684 | 666 | ||
685 | io_data->kiocb->private = NULL; | 667 | io_data->kiocb->private = NULL; |
686 | if (io_data->read) | 668 | if (io_data->read) |
687 | kfree(io_data->iovec); | 669 | kfree(io_data->to_free); |
688 | kfree(io_data->buf); | 670 | kfree(io_data->buf); |
689 | kfree(io_data); | 671 | kfree(io_data); |
690 | } | 672 | } |
@@ -743,6 +725,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
743 | * before the waiting completes, so do not assign to 'gadget' earlier | 725 | * before the waiting completes, so do not assign to 'gadget' earlier |
744 | */ | 726 | */ |
745 | struct usb_gadget *gadget = epfile->ffs->gadget; | 727 | struct usb_gadget *gadget = epfile->ffs->gadget; |
728 | size_t copied; | ||
746 | 729 | ||
747 | spin_lock_irq(&epfile->ffs->eps_lock); | 730 | spin_lock_irq(&epfile->ffs->eps_lock); |
748 | /* In the meantime, endpoint got disabled or changed. */ | 731 | /* In the meantime, endpoint got disabled or changed. */ |
@@ -750,34 +733,21 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
750 | spin_unlock_irq(&epfile->ffs->eps_lock); | 733 | spin_unlock_irq(&epfile->ffs->eps_lock); |
751 | return -ESHUTDOWN; | 734 | return -ESHUTDOWN; |
752 | } | 735 | } |
736 | data_len = iov_iter_count(&io_data->data); | ||
753 | /* | 737 | /* |
754 | * Controller may require buffer size to be aligned to | 738 | * Controller may require buffer size to be aligned to |
755 | * maxpacketsize of an out endpoint. | 739 | * maxpacketsize of an out endpoint. |
756 | */ | 740 | */ |
757 | data_len = io_data->read ? | 741 | if (io_data->read) |
758 | usb_ep_align_maybe(gadget, ep->ep, io_data->len) : | 742 | data_len = usb_ep_align_maybe(gadget, ep->ep, data_len); |
759 | io_data->len; | ||
760 | spin_unlock_irq(&epfile->ffs->eps_lock); | 743 | spin_unlock_irq(&epfile->ffs->eps_lock); |
761 | 744 | ||
762 | data = kmalloc(data_len, GFP_KERNEL); | 745 | data = kmalloc(data_len, GFP_KERNEL); |
763 | if (unlikely(!data)) | 746 | if (unlikely(!data)) |
764 | return -ENOMEM; | 747 | return -ENOMEM; |
765 | if (io_data->aio && !io_data->read) { | 748 | if (!io_data->read) { |
766 | int i; | 749 | copied = copy_from_iter(data, data_len, &io_data->data); |
767 | size_t pos = 0; | 750 | if (copied != data_len) { |
768 | for (i = 0; i < io_data->nr_segs; i++) { | ||
769 | if (unlikely(copy_from_user(&data[pos], | ||
770 | io_data->iovec[i].iov_base, | ||
771 | io_data->iovec[i].iov_len))) { | ||
772 | ret = -EFAULT; | ||
773 | goto error; | ||
774 | } | ||
775 | pos += io_data->iovec[i].iov_len; | ||
776 | } | ||
777 | } else { | ||
778 | if (!io_data->read && | ||
779 | unlikely(__copy_from_user(data, io_data->buf, | ||
780 | io_data->len))) { | ||
781 | ret = -EFAULT; | 751 | ret = -EFAULT; |
782 | goto error; | 752 | goto error; |
783 | } | 753 | } |
@@ -876,10 +846,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
876 | */ | 846 | */ |
877 | ret = ep->status; | 847 | ret = ep->status; |
878 | if (io_data->read && ret > 0) { | 848 | if (io_data->read && ret > 0) { |
879 | ret = min_t(size_t, ret, io_data->len); | 849 | ret = copy_to_iter(data, ret, &io_data->data); |
880 | 850 | if (unlikely(iov_iter_count(&io_data->data))) | |
881 | if (unlikely(copy_to_user(io_data->buf, | ||
882 | data, ret))) | ||
883 | ret = -EFAULT; | 851 | ret = -EFAULT; |
884 | } | 852 | } |
885 | } | 853 | } |
@@ -898,37 +866,6 @@ error: | |||
898 | return ret; | 866 | return ret; |
899 | } | 867 | } |
900 | 868 | ||
901 | static ssize_t | ||
902 | ffs_epfile_write(struct file *file, const char __user *buf, size_t len, | ||
903 | loff_t *ptr) | ||
904 | { | ||
905 | struct ffs_io_data io_data; | ||
906 | |||
907 | ENTER(); | ||
908 | |||
909 | io_data.aio = false; | ||
910 | io_data.read = false; | ||
911 | io_data.buf = (char * __user)buf; | ||
912 | io_data.len = len; | ||
913 | |||
914 | return ffs_epfile_io(file, &io_data); | ||
915 | } | ||
916 | |||
917 | static ssize_t | ||
918 | ffs_epfile_read(struct file *file, char __user *buf, size_t len, loff_t *ptr) | ||
919 | { | ||
920 | struct ffs_io_data io_data; | ||
921 | |||
922 | ENTER(); | ||
923 | |||
924 | io_data.aio = false; | ||
925 | io_data.read = true; | ||
926 | io_data.buf = buf; | ||
927 | io_data.len = len; | ||
928 | |||
929 | return ffs_epfile_io(file, &io_data); | ||
930 | } | ||
931 | |||
932 | static int | 869 | static int |
933 | ffs_epfile_open(struct inode *inode, struct file *file) | 870 | ffs_epfile_open(struct inode *inode, struct file *file) |
934 | { | 871 | { |
@@ -965,67 +902,86 @@ static int ffs_aio_cancel(struct kiocb *kiocb) | |||
965 | return value; | 902 | return value; |
966 | } | 903 | } |
967 | 904 | ||
968 | static ssize_t ffs_epfile_aio_write(struct kiocb *kiocb, | 905 | static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) |
969 | const struct iovec *iovec, | ||
970 | unsigned long nr_segs, loff_t loff) | ||
971 | { | 906 | { |
972 | struct ffs_io_data *io_data; | 907 | struct ffs_io_data io_data, *p = &io_data; |
908 | ssize_t res; | ||
973 | 909 | ||
974 | ENTER(); | 910 | ENTER(); |
975 | 911 | ||
976 | io_data = kmalloc(sizeof(*io_data), GFP_KERNEL); | 912 | if (!is_sync_kiocb(kiocb)) { |
977 | if (unlikely(!io_data)) | 913 | p = kmalloc(sizeof(io_data), GFP_KERNEL); |
978 | return -ENOMEM; | 914 | if (unlikely(!p)) |
915 | return -ENOMEM; | ||
916 | p->aio = true; | ||
917 | } else { | ||
918 | p->aio = false; | ||
919 | } | ||
979 | 920 | ||
980 | io_data->aio = true; | 921 | p->read = false; |
981 | io_data->read = false; | 922 | p->kiocb = kiocb; |
982 | io_data->kiocb = kiocb; | 923 | p->data = *from; |
983 | io_data->iovec = iovec; | 924 | p->mm = current->mm; |
984 | io_data->nr_segs = nr_segs; | ||
985 | io_data->len = kiocb->ki_nbytes; | ||
986 | io_data->mm = current->mm; | ||
987 | 925 | ||
988 | kiocb->private = io_data; | 926 | kiocb->private = p; |
989 | 927 | ||
990 | kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); | 928 | kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); |
991 | 929 | ||
992 | return ffs_epfile_io(kiocb->ki_filp, io_data); | 930 | res = ffs_epfile_io(kiocb->ki_filp, p); |
931 | if (res == -EIOCBQUEUED) | ||
932 | return res; | ||
933 | if (p->aio) | ||
934 | kfree(p); | ||
935 | else | ||
936 | *from = p->data; | ||
937 | return res; | ||
993 | } | 938 | } |
994 | 939 | ||
995 | static ssize_t ffs_epfile_aio_read(struct kiocb *kiocb, | 940 | static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) |
996 | const struct iovec *iovec, | ||
997 | unsigned long nr_segs, loff_t loff) | ||
998 | { | 941 | { |
999 | struct ffs_io_data *io_data; | 942 | struct ffs_io_data io_data, *p = &io_data; |
1000 | struct iovec *iovec_copy; | 943 | ssize_t res; |
1001 | 944 | ||
1002 | ENTER(); | 945 | ENTER(); |
1003 | 946 | ||
1004 | iovec_copy = kmalloc_array(nr_segs, sizeof(*iovec_copy), GFP_KERNEL); | 947 | if (!is_sync_kiocb(kiocb)) { |
1005 | if (unlikely(!iovec_copy)) | 948 | p = kmalloc(sizeof(io_data), GFP_KERNEL); |
1006 | return -ENOMEM; | 949 | if (unlikely(!p)) |
1007 | 950 | return -ENOMEM; | |
1008 | memcpy(iovec_copy, iovec, sizeof(struct iovec)*nr_segs); | 951 | p->aio = true; |
1009 | 952 | } else { | |
1010 | io_data = kmalloc(sizeof(*io_data), GFP_KERNEL); | 953 | p->aio = false; |
1011 | if (unlikely(!io_data)) { | ||
1012 | kfree(iovec_copy); | ||
1013 | return -ENOMEM; | ||
1014 | } | 954 | } |
1015 | 955 | ||
1016 | io_data->aio = true; | 956 | p->read = true; |
1017 | io_data->read = true; | 957 | p->kiocb = kiocb; |
1018 | io_data->kiocb = kiocb; | 958 | if (p->aio) { |
1019 | io_data->iovec = iovec_copy; | 959 | p->to_free = dup_iter(&p->data, to, GFP_KERNEL); |
1020 | io_data->nr_segs = nr_segs; | 960 | if (!p->to_free) { |
1021 | io_data->len = kiocb->ki_nbytes; | 961 | kfree(p); |
1022 | io_data->mm = current->mm; | 962 | return -ENOMEM; |
963 | } | ||
964 | } else { | ||
965 | p->data = *to; | ||
966 | p->to_free = NULL; | ||
967 | } | ||
968 | p->mm = current->mm; | ||
1023 | 969 | ||
1024 | kiocb->private = io_data; | 970 | kiocb->private = p; |
1025 | 971 | ||
1026 | kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); | 972 | kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); |
1027 | 973 | ||
1028 | return ffs_epfile_io(kiocb->ki_filp, io_data); | 974 | res = ffs_epfile_io(kiocb->ki_filp, p); |
975 | if (res == -EIOCBQUEUED) | ||
976 | return res; | ||
977 | |||
978 | if (p->aio) { | ||
979 | kfree(p->to_free); | ||
980 | kfree(p); | ||
981 | } else { | ||
982 | *to = p->data; | ||
983 | } | ||
984 | return res; | ||
1029 | } | 985 | } |
1030 | 986 | ||
1031 | static int | 987 | static int |
@@ -1105,10 +1061,8 @@ static const struct file_operations ffs_epfile_operations = { | |||
1105 | .llseek = no_llseek, | 1061 | .llseek = no_llseek, |
1106 | 1062 | ||
1107 | .open = ffs_epfile_open, | 1063 | .open = ffs_epfile_open, |
1108 | .write = ffs_epfile_write, | 1064 | .write_iter = ffs_epfile_write_iter, |
1109 | .read = ffs_epfile_read, | 1065 | .read_iter = ffs_epfile_read_iter, |
1110 | .aio_write = ffs_epfile_aio_write, | ||
1111 | .aio_read = ffs_epfile_aio_read, | ||
1112 | .release = ffs_epfile_release, | 1066 | .release = ffs_epfile_release, |
1113 | .unlocked_ioctl = ffs_epfile_ioctl, | 1067 | .unlocked_ioctl = ffs_epfile_ioctl, |
1114 | }; | 1068 | }; |
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 426d69a9c018..13dfc9915b1d 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c | |||
@@ -569,7 +569,7 @@ fail: | |||
569 | return status; | 569 | return status; |
570 | } | 570 | } |
571 | 571 | ||
572 | const struct file_operations f_hidg_fops = { | 572 | static const struct file_operations f_hidg_fops = { |
573 | .owner = THIS_MODULE, | 573 | .owner = THIS_MODULE, |
574 | .open = f_hidg_open, | 574 | .open = f_hidg_open, |
575 | .release = f_hidg_release, | 575 | .release = f_hidg_release, |
@@ -908,7 +908,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) | |||
908 | 908 | ||
909 | /* disable/free request and end point */ | 909 | /* disable/free request and end point */ |
910 | usb_ep_disable(hidg->in_ep); | 910 | usb_ep_disable(hidg->in_ep); |
911 | usb_ep_dequeue(hidg->in_ep, hidg->req); | ||
912 | kfree(hidg->req->buf); | 911 | kfree(hidg->req->buf); |
913 | usb_ep_free_request(hidg->in_ep, hidg->req); | 912 | usb_ep_free_request(hidg->in_ep, hidg->req); |
914 | 913 | ||
diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index 298b46112b1a..39f49f1ad22f 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c | |||
@@ -289,8 +289,7 @@ static void disable_loopback(struct f_loopback *loop) | |||
289 | struct usb_composite_dev *cdev; | 289 | struct usb_composite_dev *cdev; |
290 | 290 | ||
291 | cdev = loop->function.config->cdev; | 291 | cdev = loop->function.config->cdev; |
292 | disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL, NULL, | 292 | disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL); |
293 | NULL); | ||
294 | VDBG(cdev, "%s disabled\n", loop->function.name); | 293 | VDBG(cdev, "%s disabled\n", loop->function.name); |
295 | } | 294 | } |
296 | 295 | ||
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 811929cd4c9e..3cc109f3c9c8 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c | |||
@@ -1085,7 +1085,7 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) | |||
1085 | if (!curlun) { /* Unsupported LUNs are okay */ | 1085 | if (!curlun) { /* Unsupported LUNs are okay */ |
1086 | common->bad_lun_okay = 1; | 1086 | common->bad_lun_okay = 1; |
1087 | memset(buf, 0, 36); | 1087 | memset(buf, 0, 36); |
1088 | buf[0] = 0x7f; /* Unsupported, no device-type */ | 1088 | buf[0] = TYPE_NO_LUN; /* Unsupported, no device-type */ |
1089 | buf[4] = 31; /* Additional length */ | 1089 | buf[4] = 31; /* Additional length */ |
1090 | return 36; | 1090 | return 36; |
1091 | } | 1091 | } |
@@ -2624,13 +2624,10 @@ static ssize_t file_store(struct device *dev, struct device_attribute *attr, | |||
2624 | return fsg_store_file(curlun, filesem, buf, count); | 2624 | return fsg_store_file(curlun, filesem, buf, count); |
2625 | } | 2625 | } |
2626 | 2626 | ||
2627 | static DEVICE_ATTR_RW(ro); | ||
2628 | static DEVICE_ATTR_RW(nofua); | 2627 | static DEVICE_ATTR_RW(nofua); |
2629 | static DEVICE_ATTR_RW(file); | 2628 | /* mode wil be set in fsg_lun_attr_is_visible() */ |
2630 | 2629 | static DEVICE_ATTR(ro, 0, ro_show, ro_store); | |
2631 | static struct device_attribute dev_attr_ro_cdrom = __ATTR_RO(ro); | 2630 | static DEVICE_ATTR(file, 0, file_show, file_store); |
2632 | static struct device_attribute dev_attr_file_nonremovable = __ATTR_RO(file); | ||
2633 | |||
2634 | 2631 | ||
2635 | /****************************** FSG COMMON ******************************/ | 2632 | /****************************** FSG COMMON ******************************/ |
2636 | 2633 | ||
@@ -2745,40 +2742,10 @@ error_release: | |||
2745 | } | 2742 | } |
2746 | EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers); | 2743 | EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers); |
2747 | 2744 | ||
2748 | static inline void fsg_common_remove_sysfs(struct fsg_lun *lun) | ||
2749 | { | ||
2750 | device_remove_file(&lun->dev, &dev_attr_nofua); | ||
2751 | /* | ||
2752 | * device_remove_file() => | ||
2753 | * | ||
2754 | * here the attr (e.g. dev_attr_ro) is only used to be passed to: | ||
2755 | * | ||
2756 | * sysfs_remove_file() => | ||
2757 | * | ||
2758 | * here e.g. both dev_attr_ro_cdrom and dev_attr_ro are in | ||
2759 | * the same namespace and | ||
2760 | * from here only attr->name is passed to: | ||
2761 | * | ||
2762 | * sysfs_hash_and_remove() | ||
2763 | * | ||
2764 | * attr->name is the same for dev_attr_ro_cdrom and | ||
2765 | * dev_attr_ro | ||
2766 | * attr->name is the same for dev_attr_file and | ||
2767 | * dev_attr_file_nonremovable | ||
2768 | * | ||
2769 | * so we don't differentiate between removing e.g. dev_attr_ro_cdrom | ||
2770 | * and dev_attr_ro | ||
2771 | */ | ||
2772 | device_remove_file(&lun->dev, &dev_attr_ro); | ||
2773 | device_remove_file(&lun->dev, &dev_attr_file); | ||
2774 | } | ||
2775 | |||
2776 | void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs) | 2745 | void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs) |
2777 | { | 2746 | { |
2778 | if (sysfs) { | 2747 | if (sysfs) |
2779 | fsg_common_remove_sysfs(lun); | ||
2780 | device_unregister(&lun->dev); | 2748 | device_unregister(&lun->dev); |
2781 | } | ||
2782 | fsg_lun_close(lun); | 2749 | fsg_lun_close(lun); |
2783 | kfree(lun); | 2750 | kfree(lun); |
2784 | } | 2751 | } |
@@ -2877,41 +2844,35 @@ int fsg_common_set_cdev(struct fsg_common *common, | |||
2877 | } | 2844 | } |
2878 | EXPORT_SYMBOL_GPL(fsg_common_set_cdev); | 2845 | EXPORT_SYMBOL_GPL(fsg_common_set_cdev); |
2879 | 2846 | ||
2880 | static inline int fsg_common_add_sysfs(struct fsg_common *common, | 2847 | static struct attribute *fsg_lun_dev_attrs[] = { |
2881 | struct fsg_lun *lun) | 2848 | &dev_attr_ro.attr, |
2882 | { | 2849 | &dev_attr_file.attr, |
2883 | int rc; | 2850 | &dev_attr_nofua.attr, |
2851 | NULL | ||
2852 | }; | ||
2884 | 2853 | ||
2885 | rc = device_register(&lun->dev); | 2854 | static umode_t fsg_lun_dev_is_visible(struct kobject *kobj, |
2886 | if (rc) { | 2855 | struct attribute *attr, int idx) |
2887 | put_device(&lun->dev); | 2856 | { |
2888 | return rc; | 2857 | struct device *dev = kobj_to_dev(kobj); |
2889 | } | 2858 | struct fsg_lun *lun = fsg_lun_from_dev(dev); |
2890 | 2859 | ||
2891 | rc = device_create_file(&lun->dev, | 2860 | if (attr == &dev_attr_ro.attr) |
2892 | lun->cdrom | 2861 | return lun->cdrom ? S_IRUGO : (S_IWUSR | S_IRUGO); |
2893 | ? &dev_attr_ro_cdrom | 2862 | if (attr == &dev_attr_file.attr) |
2894 | : &dev_attr_ro); | 2863 | return lun->removable ? (S_IWUSR | S_IRUGO) : S_IRUGO; |
2895 | if (rc) | 2864 | return attr->mode; |
2896 | goto error; | 2865 | } |
2897 | rc = device_create_file(&lun->dev, | ||
2898 | lun->removable | ||
2899 | ? &dev_attr_file | ||
2900 | : &dev_attr_file_nonremovable); | ||
2901 | if (rc) | ||
2902 | goto error; | ||
2903 | rc = device_create_file(&lun->dev, &dev_attr_nofua); | ||
2904 | if (rc) | ||
2905 | goto error; | ||
2906 | 2866 | ||
2907 | return 0; | 2867 | static const struct attribute_group fsg_lun_dev_group = { |
2868 | .attrs = fsg_lun_dev_attrs, | ||
2869 | .is_visible = fsg_lun_dev_is_visible, | ||
2870 | }; | ||
2908 | 2871 | ||
2909 | error: | 2872 | static const struct attribute_group *fsg_lun_dev_groups[] = { |
2910 | /* removing nonexistent files is a no-op */ | 2873 | &fsg_lun_dev_group, |
2911 | fsg_common_remove_sysfs(lun); | 2874 | NULL |
2912 | device_unregister(&lun->dev); | 2875 | }; |
2913 | return rc; | ||
2914 | } | ||
2915 | 2876 | ||
2916 | int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, | 2877 | int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, |
2917 | unsigned int id, const char *name, | 2878 | unsigned int id, const char *name, |
@@ -2949,13 +2910,15 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, | |||
2949 | } else { | 2910 | } else { |
2950 | lun->dev.release = fsg_lun_release; | 2911 | lun->dev.release = fsg_lun_release; |
2951 | lun->dev.parent = &common->gadget->dev; | 2912 | lun->dev.parent = &common->gadget->dev; |
2913 | lun->dev.groups = fsg_lun_dev_groups; | ||
2952 | dev_set_drvdata(&lun->dev, &common->filesem); | 2914 | dev_set_drvdata(&lun->dev, &common->filesem); |
2953 | dev_set_name(&lun->dev, "%s", name); | 2915 | dev_set_name(&lun->dev, "%s", name); |
2954 | lun->name = dev_name(&lun->dev); | 2916 | lun->name = dev_name(&lun->dev); |
2955 | 2917 | ||
2956 | rc = fsg_common_add_sysfs(common, lun); | 2918 | rc = device_register(&lun->dev); |
2957 | if (rc) { | 2919 | if (rc) { |
2958 | pr_info("failed to register LUN%d: %d\n", id, rc); | 2920 | pr_info("failed to register LUN%d: %d\n", id, rc); |
2921 | put_device(&lun->dev); | ||
2959 | goto error_sysfs; | 2922 | goto error_sysfs; |
2960 | } | 2923 | } |
2961 | } | 2924 | } |
@@ -2988,10 +2951,8 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, | |||
2988 | return 0; | 2951 | return 0; |
2989 | 2952 | ||
2990 | error_lun: | 2953 | error_lun: |
2991 | if (common->sysfs) { | 2954 | if (common->sysfs) |
2992 | fsg_common_remove_sysfs(lun); | ||
2993 | device_unregister(&lun->dev); | 2955 | device_unregister(&lun->dev); |
2994 | } | ||
2995 | fsg_lun_close(lun); | 2956 | fsg_lun_close(lun); |
2996 | common->luns[id] = NULL; | 2957 | common->luns[id] = NULL; |
2997 | error_sysfs: | 2958 | error_sysfs: |
@@ -3077,8 +3038,6 @@ static void fsg_common_release(struct kref *ref) | |||
3077 | struct fsg_lun *lun = *lun_it; | 3038 | struct fsg_lun *lun = *lun_it; |
3078 | if (!lun) | 3039 | if (!lun) |
3079 | continue; | 3040 | continue; |
3080 | if (common->sysfs) | ||
3081 | fsg_common_remove_sysfs(lun); | ||
3082 | fsg_lun_close(lun); | 3041 | fsg_lun_close(lun); |
3083 | if (common->sysfs) | 3042 | if (common->sysfs) |
3084 | device_unregister(&lun->dev); | 3043 | device_unregister(&lun->dev); |
diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c index c89e96cfa3e4..c0c3ef272714 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c | |||
@@ -417,7 +417,10 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
417 | return -EINVAL; | 417 | return -EINVAL; |
418 | 418 | ||
419 | spin_lock(&port->lock); | 419 | spin_lock(&port->lock); |
420 | __pn_reset(f); | 420 | |
421 | if (fp->in_ep->driver_data) | ||
422 | __pn_reset(f); | ||
423 | |||
421 | if (alt == 1) { | 424 | if (alt == 1) { |
422 | int i; | 425 | int i; |
423 | 426 | ||
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c new file mode 100644 index 000000000000..44173df27273 --- /dev/null +++ b/drivers/usb/gadget/function/f_printer.c | |||
@@ -0,0 +1,1471 @@ | |||
1 | /* | ||
2 | * f_printer.c - USB printer function driver | ||
3 | * | ||
4 | * Copied from drivers/usb/gadget/legacy/printer.c, | ||
5 | * which was: | ||
6 | * | ||
7 | * printer.c -- Printer gadget driver | ||
8 | * | ||
9 | * Copyright (C) 2003-2005 David Brownell | ||
10 | * Copyright (C) 2006 Craig W. Nadler | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/mutex.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/idr.h> | ||
28 | #include <linux/timer.h> | ||
29 | #include <linux/list.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/moduleparam.h> | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <linux/types.h> | ||
36 | #include <linux/ctype.h> | ||
37 | #include <linux/cdev.h> | ||
38 | |||
39 | #include <asm/byteorder.h> | ||
40 | #include <linux/io.h> | ||
41 | #include <linux/irq.h> | ||
42 | #include <linux/uaccess.h> | ||
43 | #include <asm/unaligned.h> | ||
44 | |||
45 | #include <linux/usb/ch9.h> | ||
46 | #include <linux/usb/composite.h> | ||
47 | #include <linux/usb/gadget.h> | ||
48 | #include <linux/usb/g_printer.h> | ||
49 | |||
50 | #include "u_printer.h" | ||
51 | |||
52 | #define PNP_STRING_LEN 1024 | ||
53 | #define PRINTER_MINORS 4 | ||
54 | #define GET_DEVICE_ID 0 | ||
55 | #define GET_PORT_STATUS 1 | ||
56 | #define SOFT_RESET 2 | ||
57 | |||
58 | static int major, minors; | ||
59 | static struct class *usb_gadget_class; | ||
60 | static DEFINE_IDA(printer_ida); | ||
61 | static DEFINE_MUTEX(printer_ida_lock); /* protects access do printer_ida */ | ||
62 | |||
63 | /*-------------------------------------------------------------------------*/ | ||
64 | |||
65 | struct printer_dev { | ||
66 | spinlock_t lock; /* lock this structure */ | ||
67 | /* lock buffer lists during read/write calls */ | ||
68 | struct mutex lock_printer_io; | ||
69 | struct usb_gadget *gadget; | ||
70 | s8 interface; | ||
71 | struct usb_ep *in_ep, *out_ep; | ||
72 | |||
73 | struct list_head rx_reqs; /* List of free RX structs */ | ||
74 | struct list_head rx_reqs_active; /* List of Active RX xfers */ | ||
75 | struct list_head rx_buffers; /* List of completed xfers */ | ||
76 | /* wait until there is data to be read. */ | ||
77 | wait_queue_head_t rx_wait; | ||
78 | struct list_head tx_reqs; /* List of free TX structs */ | ||
79 | struct list_head tx_reqs_active; /* List of Active TX xfers */ | ||
80 | /* Wait until there are write buffers available to use. */ | ||
81 | wait_queue_head_t tx_wait; | ||
82 | /* Wait until all write buffers have been sent. */ | ||
83 | wait_queue_head_t tx_flush_wait; | ||
84 | struct usb_request *current_rx_req; | ||
85 | size_t current_rx_bytes; | ||
86 | u8 *current_rx_buf; | ||
87 | u8 printer_status; | ||
88 | u8 reset_printer; | ||
89 | int minor; | ||
90 | struct cdev printer_cdev; | ||
91 | u8 printer_cdev_open; | ||
92 | wait_queue_head_t wait; | ||
93 | unsigned q_len; | ||
94 | char *pnp_string; /* We don't own memory! */ | ||
95 | struct usb_function function; | ||
96 | }; | ||
97 | |||
98 | static inline struct printer_dev *func_to_printer(struct usb_function *f) | ||
99 | { | ||
100 | return container_of(f, struct printer_dev, function); | ||
101 | } | ||
102 | |||
103 | /*-------------------------------------------------------------------------*/ | ||
104 | |||
105 | /* | ||
106 | * DESCRIPTORS ... most are static, but strings and (full) configuration | ||
107 | * descriptors are built on demand. | ||
108 | */ | ||
109 | |||
110 | /* holds our biggest descriptor */ | ||
111 | #define USB_DESC_BUFSIZE 256 | ||
112 | #define USB_BUFSIZE 8192 | ||
113 | |||
114 | static struct usb_interface_descriptor intf_desc = { | ||
115 | .bLength = sizeof(intf_desc), | ||
116 | .bDescriptorType = USB_DT_INTERFACE, | ||
117 | .bNumEndpoints = 2, | ||
118 | .bInterfaceClass = USB_CLASS_PRINTER, | ||
119 | .bInterfaceSubClass = 1, /* Printer Sub-Class */ | ||
120 | .bInterfaceProtocol = 2, /* Bi-Directional */ | ||
121 | .iInterface = 0 | ||
122 | }; | ||
123 | |||
124 | static struct usb_endpoint_descriptor fs_ep_in_desc = { | ||
125 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
126 | .bDescriptorType = USB_DT_ENDPOINT, | ||
127 | .bEndpointAddress = USB_DIR_IN, | ||
128 | .bmAttributes = USB_ENDPOINT_XFER_BULK | ||
129 | }; | ||
130 | |||
131 | static struct usb_endpoint_descriptor fs_ep_out_desc = { | ||
132 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
133 | .bDescriptorType = USB_DT_ENDPOINT, | ||
134 | .bEndpointAddress = USB_DIR_OUT, | ||
135 | .bmAttributes = USB_ENDPOINT_XFER_BULK | ||
136 | }; | ||
137 | |||
138 | static struct usb_descriptor_header *fs_printer_function[] = { | ||
139 | (struct usb_descriptor_header *) &intf_desc, | ||
140 | (struct usb_descriptor_header *) &fs_ep_in_desc, | ||
141 | (struct usb_descriptor_header *) &fs_ep_out_desc, | ||
142 | NULL | ||
143 | }; | ||
144 | |||
145 | /* | ||
146 | * usb 2.0 devices need to expose both high speed and full speed | ||
147 | * descriptors, unless they only run at full speed. | ||
148 | */ | ||
149 | |||
150 | static struct usb_endpoint_descriptor hs_ep_in_desc = { | ||
151 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
152 | .bDescriptorType = USB_DT_ENDPOINT, | ||
153 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
154 | .wMaxPacketSize = cpu_to_le16(512) | ||
155 | }; | ||
156 | |||
157 | static struct usb_endpoint_descriptor hs_ep_out_desc = { | ||
158 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
159 | .bDescriptorType = USB_DT_ENDPOINT, | ||
160 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
161 | .wMaxPacketSize = cpu_to_le16(512) | ||
162 | }; | ||
163 | |||
164 | static struct usb_qualifier_descriptor dev_qualifier = { | ||
165 | .bLength = sizeof(dev_qualifier), | ||
166 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, | ||
167 | .bcdUSB = cpu_to_le16(0x0200), | ||
168 | .bDeviceClass = USB_CLASS_PRINTER, | ||
169 | .bNumConfigurations = 1 | ||
170 | }; | ||
171 | |||
172 | static struct usb_descriptor_header *hs_printer_function[] = { | ||
173 | (struct usb_descriptor_header *) &intf_desc, | ||
174 | (struct usb_descriptor_header *) &hs_ep_in_desc, | ||
175 | (struct usb_descriptor_header *) &hs_ep_out_desc, | ||
176 | NULL | ||
177 | }; | ||
178 | |||
179 | /* | ||
180 | * Added endpoint descriptors for 3.0 devices | ||
181 | */ | ||
182 | |||
183 | static struct usb_endpoint_descriptor ss_ep_in_desc = { | ||
184 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
185 | .bDescriptorType = USB_DT_ENDPOINT, | ||
186 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
187 | .wMaxPacketSize = cpu_to_le16(1024), | ||
188 | }; | ||
189 | |||
190 | static struct usb_ss_ep_comp_descriptor ss_ep_in_comp_desc = { | ||
191 | .bLength = sizeof(ss_ep_in_comp_desc), | ||
192 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
193 | }; | ||
194 | |||
195 | static struct usb_endpoint_descriptor ss_ep_out_desc = { | ||
196 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
197 | .bDescriptorType = USB_DT_ENDPOINT, | ||
198 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
199 | .wMaxPacketSize = cpu_to_le16(1024), | ||
200 | }; | ||
201 | |||
202 | static struct usb_ss_ep_comp_descriptor ss_ep_out_comp_desc = { | ||
203 | .bLength = sizeof(ss_ep_out_comp_desc), | ||
204 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
205 | }; | ||
206 | |||
207 | static struct usb_descriptor_header *ss_printer_function[] = { | ||
208 | (struct usb_descriptor_header *) &intf_desc, | ||
209 | (struct usb_descriptor_header *) &ss_ep_in_desc, | ||
210 | (struct usb_descriptor_header *) &ss_ep_in_comp_desc, | ||
211 | (struct usb_descriptor_header *) &ss_ep_out_desc, | ||
212 | (struct usb_descriptor_header *) &ss_ep_out_comp_desc, | ||
213 | NULL | ||
214 | }; | ||
215 | |||
216 | /* maxpacket and other transfer characteristics vary by speed. */ | ||
217 | static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget, | ||
218 | struct usb_endpoint_descriptor *fs, | ||
219 | struct usb_endpoint_descriptor *hs, | ||
220 | struct usb_endpoint_descriptor *ss) | ||
221 | { | ||
222 | switch (gadget->speed) { | ||
223 | case USB_SPEED_SUPER: | ||
224 | return ss; | ||
225 | case USB_SPEED_HIGH: | ||
226 | return hs; | ||
227 | default: | ||
228 | return fs; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /*-------------------------------------------------------------------------*/ | ||
233 | |||
234 | static struct usb_request * | ||
235 | printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags) | ||
236 | { | ||
237 | struct usb_request *req; | ||
238 | |||
239 | req = usb_ep_alloc_request(ep, gfp_flags); | ||
240 | |||
241 | if (req != NULL) { | ||
242 | req->length = len; | ||
243 | req->buf = kmalloc(len, gfp_flags); | ||
244 | if (req->buf == NULL) { | ||
245 | usb_ep_free_request(ep, req); | ||
246 | return NULL; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | return req; | ||
251 | } | ||
252 | |||
253 | static void | ||
254 | printer_req_free(struct usb_ep *ep, struct usb_request *req) | ||
255 | { | ||
256 | if (ep != NULL && req != NULL) { | ||
257 | kfree(req->buf); | ||
258 | usb_ep_free_request(ep, req); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /*-------------------------------------------------------------------------*/ | ||
263 | |||
264 | static void rx_complete(struct usb_ep *ep, struct usb_request *req) | ||
265 | { | ||
266 | struct printer_dev *dev = ep->driver_data; | ||
267 | int status = req->status; | ||
268 | unsigned long flags; | ||
269 | |||
270 | spin_lock_irqsave(&dev->lock, flags); | ||
271 | |||
272 | list_del_init(&req->list); /* Remode from Active List */ | ||
273 | |||
274 | switch (status) { | ||
275 | |||
276 | /* normal completion */ | ||
277 | case 0: | ||
278 | if (req->actual > 0) { | ||
279 | list_add_tail(&req->list, &dev->rx_buffers); | ||
280 | DBG(dev, "G_Printer : rx length %d\n", req->actual); | ||
281 | } else { | ||
282 | list_add(&req->list, &dev->rx_reqs); | ||
283 | } | ||
284 | break; | ||
285 | |||
286 | /* software-driven interface shutdown */ | ||
287 | case -ECONNRESET: /* unlink */ | ||
288 | case -ESHUTDOWN: /* disconnect etc */ | ||
289 | VDBG(dev, "rx shutdown, code %d\n", status); | ||
290 | list_add(&req->list, &dev->rx_reqs); | ||
291 | break; | ||
292 | |||
293 | /* for hardware automagic (such as pxa) */ | ||
294 | case -ECONNABORTED: /* endpoint reset */ | ||
295 | DBG(dev, "rx %s reset\n", ep->name); | ||
296 | list_add(&req->list, &dev->rx_reqs); | ||
297 | break; | ||
298 | |||
299 | /* data overrun */ | ||
300 | case -EOVERFLOW: | ||
301 | /* FALLTHROUGH */ | ||
302 | |||
303 | default: | ||
304 | DBG(dev, "rx status %d\n", status); | ||
305 | list_add(&req->list, &dev->rx_reqs); | ||
306 | break; | ||
307 | } | ||
308 | |||
309 | wake_up_interruptible(&dev->rx_wait); | ||
310 | spin_unlock_irqrestore(&dev->lock, flags); | ||
311 | } | ||
312 | |||
313 | static void tx_complete(struct usb_ep *ep, struct usb_request *req) | ||
314 | { | ||
315 | struct printer_dev *dev = ep->driver_data; | ||
316 | |||
317 | switch (req->status) { | ||
318 | default: | ||
319 | VDBG(dev, "tx err %d\n", req->status); | ||
320 | /* FALLTHROUGH */ | ||
321 | case -ECONNRESET: /* unlink */ | ||
322 | case -ESHUTDOWN: /* disconnect etc */ | ||
323 | break; | ||
324 | case 0: | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | spin_lock(&dev->lock); | ||
329 | /* Take the request struct off the active list and put it on the | ||
330 | * free list. | ||
331 | */ | ||
332 | list_del_init(&req->list); | ||
333 | list_add(&req->list, &dev->tx_reqs); | ||
334 | wake_up_interruptible(&dev->tx_wait); | ||
335 | if (likely(list_empty(&dev->tx_reqs_active))) | ||
336 | wake_up_interruptible(&dev->tx_flush_wait); | ||
337 | |||
338 | spin_unlock(&dev->lock); | ||
339 | } | ||
340 | |||
341 | /*-------------------------------------------------------------------------*/ | ||
342 | |||
343 | static int | ||
344 | printer_open(struct inode *inode, struct file *fd) | ||
345 | { | ||
346 | struct printer_dev *dev; | ||
347 | unsigned long flags; | ||
348 | int ret = -EBUSY; | ||
349 | |||
350 | dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev); | ||
351 | |||
352 | spin_lock_irqsave(&dev->lock, flags); | ||
353 | |||
354 | if (!dev->printer_cdev_open) { | ||
355 | dev->printer_cdev_open = 1; | ||
356 | fd->private_data = dev; | ||
357 | ret = 0; | ||
358 | /* Change the printer status to show that it's on-line. */ | ||
359 | dev->printer_status |= PRINTER_SELECTED; | ||
360 | } | ||
361 | |||
362 | spin_unlock_irqrestore(&dev->lock, flags); | ||
363 | |||
364 | DBG(dev, "printer_open returned %x\n", ret); | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | static int | ||
369 | printer_close(struct inode *inode, struct file *fd) | ||
370 | { | ||
371 | struct printer_dev *dev = fd->private_data; | ||
372 | unsigned long flags; | ||
373 | |||
374 | spin_lock_irqsave(&dev->lock, flags); | ||
375 | dev->printer_cdev_open = 0; | ||
376 | fd->private_data = NULL; | ||
377 | /* Change printer status to show that the printer is off-line. */ | ||
378 | dev->printer_status &= ~PRINTER_SELECTED; | ||
379 | spin_unlock_irqrestore(&dev->lock, flags); | ||
380 | |||
381 | DBG(dev, "printer_close\n"); | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | /* This function must be called with interrupts turned off. */ | ||
387 | static void | ||
388 | setup_rx_reqs(struct printer_dev *dev) | ||
389 | { | ||
390 | struct usb_request *req; | ||
391 | |||
392 | while (likely(!list_empty(&dev->rx_reqs))) { | ||
393 | int error; | ||
394 | |||
395 | req = container_of(dev->rx_reqs.next, | ||
396 | struct usb_request, list); | ||
397 | list_del_init(&req->list); | ||
398 | |||
399 | /* The USB Host sends us whatever amount of data it wants to | ||
400 | * so we always set the length field to the full USB_BUFSIZE. | ||
401 | * If the amount of data is more than the read() caller asked | ||
402 | * for it will be stored in the request buffer until it is | ||
403 | * asked for by read(). | ||
404 | */ | ||
405 | req->length = USB_BUFSIZE; | ||
406 | req->complete = rx_complete; | ||
407 | |||
408 | /* here, we unlock, and only unlock, to avoid deadlock. */ | ||
409 | spin_unlock(&dev->lock); | ||
410 | error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC); | ||
411 | spin_lock(&dev->lock); | ||
412 | if (error) { | ||
413 | DBG(dev, "rx submit --> %d\n", error); | ||
414 | list_add(&req->list, &dev->rx_reqs); | ||
415 | break; | ||
416 | } | ||
417 | /* if the req is empty, then add it into dev->rx_reqs_active. */ | ||
418 | else if (list_empty(&req->list)) | ||
419 | list_add(&req->list, &dev->rx_reqs_active); | ||
420 | } | ||
421 | } | ||
422 | |||
423 | static ssize_t | ||
424 | printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) | ||
425 | { | ||
426 | struct printer_dev *dev = fd->private_data; | ||
427 | unsigned long flags; | ||
428 | size_t size; | ||
429 | size_t bytes_copied; | ||
430 | struct usb_request *req; | ||
431 | /* This is a pointer to the current USB rx request. */ | ||
432 | struct usb_request *current_rx_req; | ||
433 | /* This is the number of bytes in the current rx buffer. */ | ||
434 | size_t current_rx_bytes; | ||
435 | /* This is a pointer to the current rx buffer. */ | ||
436 | u8 *current_rx_buf; | ||
437 | |||
438 | if (len == 0) | ||
439 | return -EINVAL; | ||
440 | |||
441 | DBG(dev, "printer_read trying to read %d bytes\n", (int)len); | ||
442 | |||
443 | mutex_lock(&dev->lock_printer_io); | ||
444 | spin_lock_irqsave(&dev->lock, flags); | ||
445 | |||
446 | /* We will use this flag later to check if a printer reset happened | ||
447 | * after we turn interrupts back on. | ||
448 | */ | ||
449 | dev->reset_printer = 0; | ||
450 | |||
451 | setup_rx_reqs(dev); | ||
452 | |||
453 | bytes_copied = 0; | ||
454 | current_rx_req = dev->current_rx_req; | ||
455 | current_rx_bytes = dev->current_rx_bytes; | ||
456 | current_rx_buf = dev->current_rx_buf; | ||
457 | dev->current_rx_req = NULL; | ||
458 | dev->current_rx_bytes = 0; | ||
459 | dev->current_rx_buf = NULL; | ||
460 | |||
461 | /* Check if there is any data in the read buffers. Please note that | ||
462 | * current_rx_bytes is the number of bytes in the current rx buffer. | ||
463 | * If it is zero then check if there are any other rx_buffers that | ||
464 | * are on the completed list. We are only out of data if all rx | ||
465 | * buffers are empty. | ||
466 | */ | ||
467 | if ((current_rx_bytes == 0) && | ||
468 | (likely(list_empty(&dev->rx_buffers)))) { | ||
469 | /* Turn interrupts back on before sleeping. */ | ||
470 | spin_unlock_irqrestore(&dev->lock, flags); | ||
471 | |||
472 | /* | ||
473 | * If no data is available check if this is a NON-Blocking | ||
474 | * call or not. | ||
475 | */ | ||
476 | if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { | ||
477 | mutex_unlock(&dev->lock_printer_io); | ||
478 | return -EAGAIN; | ||
479 | } | ||
480 | |||
481 | /* Sleep until data is available */ | ||
482 | wait_event_interruptible(dev->rx_wait, | ||
483 | (likely(!list_empty(&dev->rx_buffers)))); | ||
484 | spin_lock_irqsave(&dev->lock, flags); | ||
485 | } | ||
486 | |||
487 | /* We have data to return then copy it to the caller's buffer.*/ | ||
488 | while ((current_rx_bytes || likely(!list_empty(&dev->rx_buffers))) | ||
489 | && len) { | ||
490 | if (current_rx_bytes == 0) { | ||
491 | req = container_of(dev->rx_buffers.next, | ||
492 | struct usb_request, list); | ||
493 | list_del_init(&req->list); | ||
494 | |||
495 | if (req->actual && req->buf) { | ||
496 | current_rx_req = req; | ||
497 | current_rx_bytes = req->actual; | ||
498 | current_rx_buf = req->buf; | ||
499 | } else { | ||
500 | list_add(&req->list, &dev->rx_reqs); | ||
501 | continue; | ||
502 | } | ||
503 | } | ||
504 | |||
505 | /* Don't leave irqs off while doing memory copies */ | ||
506 | spin_unlock_irqrestore(&dev->lock, flags); | ||
507 | |||
508 | if (len > current_rx_bytes) | ||
509 | size = current_rx_bytes; | ||
510 | else | ||
511 | size = len; | ||
512 | |||
513 | size -= copy_to_user(buf, current_rx_buf, size); | ||
514 | bytes_copied += size; | ||
515 | len -= size; | ||
516 | buf += size; | ||
517 | |||
518 | spin_lock_irqsave(&dev->lock, flags); | ||
519 | |||
520 | /* We've disconnected or reset so return. */ | ||
521 | if (dev->reset_printer) { | ||
522 | list_add(¤t_rx_req->list, &dev->rx_reqs); | ||
523 | spin_unlock_irqrestore(&dev->lock, flags); | ||
524 | mutex_unlock(&dev->lock_printer_io); | ||
525 | return -EAGAIN; | ||
526 | } | ||
527 | |||
528 | /* If we not returning all the data left in this RX request | ||
529 | * buffer then adjust the amount of data left in the buffer. | ||
530 | * Othewise if we are done with this RX request buffer then | ||
531 | * requeue it to get any incoming data from the USB host. | ||
532 | */ | ||
533 | if (size < current_rx_bytes) { | ||
534 | current_rx_bytes -= size; | ||
535 | current_rx_buf += size; | ||
536 | } else { | ||
537 | list_add(¤t_rx_req->list, &dev->rx_reqs); | ||
538 | current_rx_bytes = 0; | ||
539 | current_rx_buf = NULL; | ||
540 | current_rx_req = NULL; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | dev->current_rx_req = current_rx_req; | ||
545 | dev->current_rx_bytes = current_rx_bytes; | ||
546 | dev->current_rx_buf = current_rx_buf; | ||
547 | |||
548 | spin_unlock_irqrestore(&dev->lock, flags); | ||
549 | mutex_unlock(&dev->lock_printer_io); | ||
550 | |||
551 | DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied); | ||
552 | |||
553 | if (bytes_copied) | ||
554 | return bytes_copied; | ||
555 | else | ||
556 | return -EAGAIN; | ||
557 | } | ||
558 | |||
559 | static ssize_t | ||
560 | printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | ||
561 | { | ||
562 | struct printer_dev *dev = fd->private_data; | ||
563 | unsigned long flags; | ||
564 | size_t size; /* Amount of data in a TX request. */ | ||
565 | size_t bytes_copied = 0; | ||
566 | struct usb_request *req; | ||
567 | |||
568 | DBG(dev, "printer_write trying to send %d bytes\n", (int)len); | ||
569 | |||
570 | if (len == 0) | ||
571 | return -EINVAL; | ||
572 | |||
573 | mutex_lock(&dev->lock_printer_io); | ||
574 | spin_lock_irqsave(&dev->lock, flags); | ||
575 | |||
576 | /* Check if a printer reset happens while we have interrupts on */ | ||
577 | dev->reset_printer = 0; | ||
578 | |||
579 | /* Check if there is any available write buffers */ | ||
580 | if (likely(list_empty(&dev->tx_reqs))) { | ||
581 | /* Turn interrupts back on before sleeping. */ | ||
582 | spin_unlock_irqrestore(&dev->lock, flags); | ||
583 | |||
584 | /* | ||
585 | * If write buffers are available check if this is | ||
586 | * a NON-Blocking call or not. | ||
587 | */ | ||
588 | if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { | ||
589 | mutex_unlock(&dev->lock_printer_io); | ||
590 | return -EAGAIN; | ||
591 | } | ||
592 | |||
593 | /* Sleep until a write buffer is available */ | ||
594 | wait_event_interruptible(dev->tx_wait, | ||
595 | (likely(!list_empty(&dev->tx_reqs)))); | ||
596 | spin_lock_irqsave(&dev->lock, flags); | ||
597 | } | ||
598 | |||
599 | while (likely(!list_empty(&dev->tx_reqs)) && len) { | ||
600 | |||
601 | if (len > USB_BUFSIZE) | ||
602 | size = USB_BUFSIZE; | ||
603 | else | ||
604 | size = len; | ||
605 | |||
606 | req = container_of(dev->tx_reqs.next, struct usb_request, | ||
607 | list); | ||
608 | list_del_init(&req->list); | ||
609 | |||
610 | req->complete = tx_complete; | ||
611 | req->length = size; | ||
612 | |||
613 | /* Check if we need to send a zero length packet. */ | ||
614 | if (len > size) | ||
615 | /* They will be more TX requests so no yet. */ | ||
616 | req->zero = 0; | ||
617 | else | ||
618 | /* If the data amount is not a multiple of the | ||
619 | * maxpacket size then send a zero length packet. | ||
620 | */ | ||
621 | req->zero = ((len % dev->in_ep->maxpacket) == 0); | ||
622 | |||
623 | /* Don't leave irqs off while doing memory copies */ | ||
624 | spin_unlock_irqrestore(&dev->lock, flags); | ||
625 | |||
626 | if (copy_from_user(req->buf, buf, size)) { | ||
627 | list_add(&req->list, &dev->tx_reqs); | ||
628 | mutex_unlock(&dev->lock_printer_io); | ||
629 | return bytes_copied; | ||
630 | } | ||
631 | |||
632 | bytes_copied += size; | ||
633 | len -= size; | ||
634 | buf += size; | ||
635 | |||
636 | spin_lock_irqsave(&dev->lock, flags); | ||
637 | |||
638 | /* We've disconnected or reset so free the req and buffer */ | ||
639 | if (dev->reset_printer) { | ||
640 | list_add(&req->list, &dev->tx_reqs); | ||
641 | spin_unlock_irqrestore(&dev->lock, flags); | ||
642 | mutex_unlock(&dev->lock_printer_io); | ||
643 | return -EAGAIN; | ||
644 | } | ||
645 | |||
646 | if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) { | ||
647 | list_add(&req->list, &dev->tx_reqs); | ||
648 | spin_unlock_irqrestore(&dev->lock, flags); | ||
649 | mutex_unlock(&dev->lock_printer_io); | ||
650 | return -EAGAIN; | ||
651 | } | ||
652 | |||
653 | list_add(&req->list, &dev->tx_reqs_active); | ||
654 | |||
655 | } | ||
656 | |||
657 | spin_unlock_irqrestore(&dev->lock, flags); | ||
658 | mutex_unlock(&dev->lock_printer_io); | ||
659 | |||
660 | DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied); | ||
661 | |||
662 | if (bytes_copied) | ||
663 | return bytes_copied; | ||
664 | else | ||
665 | return -EAGAIN; | ||
666 | } | ||
667 | |||
668 | static int | ||
669 | printer_fsync(struct file *fd, loff_t start, loff_t end, int datasync) | ||
670 | { | ||
671 | struct printer_dev *dev = fd->private_data; | ||
672 | struct inode *inode = file_inode(fd); | ||
673 | unsigned long flags; | ||
674 | int tx_list_empty; | ||
675 | |||
676 | mutex_lock(&inode->i_mutex); | ||
677 | spin_lock_irqsave(&dev->lock, flags); | ||
678 | tx_list_empty = (likely(list_empty(&dev->tx_reqs))); | ||
679 | spin_unlock_irqrestore(&dev->lock, flags); | ||
680 | |||
681 | if (!tx_list_empty) { | ||
682 | /* Sleep until all data has been sent */ | ||
683 | wait_event_interruptible(dev->tx_flush_wait, | ||
684 | (likely(list_empty(&dev->tx_reqs_active)))); | ||
685 | } | ||
686 | mutex_unlock(&inode->i_mutex); | ||
687 | |||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | static unsigned int | ||
692 | printer_poll(struct file *fd, poll_table *wait) | ||
693 | { | ||
694 | struct printer_dev *dev = fd->private_data; | ||
695 | unsigned long flags; | ||
696 | int status = 0; | ||
697 | |||
698 | mutex_lock(&dev->lock_printer_io); | ||
699 | spin_lock_irqsave(&dev->lock, flags); | ||
700 | setup_rx_reqs(dev); | ||
701 | spin_unlock_irqrestore(&dev->lock, flags); | ||
702 | mutex_unlock(&dev->lock_printer_io); | ||
703 | |||
704 | poll_wait(fd, &dev->rx_wait, wait); | ||
705 | poll_wait(fd, &dev->tx_wait, wait); | ||
706 | |||
707 | spin_lock_irqsave(&dev->lock, flags); | ||
708 | if (likely(!list_empty(&dev->tx_reqs))) | ||
709 | status |= POLLOUT | POLLWRNORM; | ||
710 | |||
711 | if (likely(dev->current_rx_bytes) || | ||
712 | likely(!list_empty(&dev->rx_buffers))) | ||
713 | status |= POLLIN | POLLRDNORM; | ||
714 | |||
715 | spin_unlock_irqrestore(&dev->lock, flags); | ||
716 | |||
717 | return status; | ||
718 | } | ||
719 | |||
720 | static long | ||
721 | printer_ioctl(struct file *fd, unsigned int code, unsigned long arg) | ||
722 | { | ||
723 | struct printer_dev *dev = fd->private_data; | ||
724 | unsigned long flags; | ||
725 | int status = 0; | ||
726 | |||
727 | DBG(dev, "printer_ioctl: cmd=0x%4.4x, arg=%lu\n", code, arg); | ||
728 | |||
729 | /* handle ioctls */ | ||
730 | |||
731 | spin_lock_irqsave(&dev->lock, flags); | ||
732 | |||
733 | switch (code) { | ||
734 | case GADGET_GET_PRINTER_STATUS: | ||
735 | status = (int)dev->printer_status; | ||
736 | break; | ||
737 | case GADGET_SET_PRINTER_STATUS: | ||
738 | dev->printer_status = (u8)arg; | ||
739 | break; | ||
740 | default: | ||
741 | /* could not handle ioctl */ | ||
742 | DBG(dev, "printer_ioctl: ERROR cmd=0x%4.4xis not supported\n", | ||
743 | code); | ||
744 | status = -ENOTTY; | ||
745 | } | ||
746 | |||
747 | spin_unlock_irqrestore(&dev->lock, flags); | ||
748 | |||
749 | return status; | ||
750 | } | ||
751 | |||
752 | /* used after endpoint configuration */ | ||
753 | static const struct file_operations printer_io_operations = { | ||
754 | .owner = THIS_MODULE, | ||
755 | .open = printer_open, | ||
756 | .read = printer_read, | ||
757 | .write = printer_write, | ||
758 | .fsync = printer_fsync, | ||
759 | .poll = printer_poll, | ||
760 | .unlocked_ioctl = printer_ioctl, | ||
761 | .release = printer_close, | ||
762 | .llseek = noop_llseek, | ||
763 | }; | ||
764 | |||
765 | /*-------------------------------------------------------------------------*/ | ||
766 | |||
767 | static int | ||
768 | set_printer_interface(struct printer_dev *dev) | ||
769 | { | ||
770 | int result = 0; | ||
771 | |||
772 | dev->in_ep->desc = ep_desc(dev->gadget, &fs_ep_in_desc, &hs_ep_in_desc, | ||
773 | &ss_ep_in_desc); | ||
774 | dev->in_ep->driver_data = dev; | ||
775 | |||
776 | dev->out_ep->desc = ep_desc(dev->gadget, &fs_ep_out_desc, | ||
777 | &hs_ep_out_desc, &ss_ep_out_desc); | ||
778 | dev->out_ep->driver_data = dev; | ||
779 | |||
780 | result = usb_ep_enable(dev->in_ep); | ||
781 | if (result != 0) { | ||
782 | DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result); | ||
783 | goto done; | ||
784 | } | ||
785 | |||
786 | result = usb_ep_enable(dev->out_ep); | ||
787 | if (result != 0) { | ||
788 | DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result); | ||
789 | goto done; | ||
790 | } | ||
791 | |||
792 | done: | ||
793 | /* on error, disable any endpoints */ | ||
794 | if (result != 0) { | ||
795 | (void) usb_ep_disable(dev->in_ep); | ||
796 | (void) usb_ep_disable(dev->out_ep); | ||
797 | dev->in_ep->desc = NULL; | ||
798 | dev->out_ep->desc = NULL; | ||
799 | } | ||
800 | |||
801 | /* caller is responsible for cleanup on error */ | ||
802 | return result; | ||
803 | } | ||
804 | |||
805 | static void printer_reset_interface(struct printer_dev *dev) | ||
806 | { | ||
807 | if (dev->interface < 0) | ||
808 | return; | ||
809 | |||
810 | DBG(dev, "%s\n", __func__); | ||
811 | |||
812 | if (dev->in_ep->desc) | ||
813 | usb_ep_disable(dev->in_ep); | ||
814 | |||
815 | if (dev->out_ep->desc) | ||
816 | usb_ep_disable(dev->out_ep); | ||
817 | |||
818 | dev->in_ep->desc = NULL; | ||
819 | dev->out_ep->desc = NULL; | ||
820 | dev->interface = -1; | ||
821 | } | ||
822 | |||
823 | /* Change our operational Interface. */ | ||
824 | static int set_interface(struct printer_dev *dev, unsigned number) | ||
825 | { | ||
826 | int result = 0; | ||
827 | |||
828 | /* Free the current interface */ | ||
829 | printer_reset_interface(dev); | ||
830 | |||
831 | result = set_printer_interface(dev); | ||
832 | if (result) | ||
833 | printer_reset_interface(dev); | ||
834 | else | ||
835 | dev->interface = number; | ||
836 | |||
837 | if (!result) | ||
838 | INFO(dev, "Using interface %x\n", number); | ||
839 | |||
840 | return result; | ||
841 | } | ||
842 | |||
843 | static void printer_soft_reset(struct printer_dev *dev) | ||
844 | { | ||
845 | struct usb_request *req; | ||
846 | |||
847 | INFO(dev, "Received Printer Reset Request\n"); | ||
848 | |||
849 | if (usb_ep_disable(dev->in_ep)) | ||
850 | DBG(dev, "Failed to disable USB in_ep\n"); | ||
851 | if (usb_ep_disable(dev->out_ep)) | ||
852 | DBG(dev, "Failed to disable USB out_ep\n"); | ||
853 | |||
854 | if (dev->current_rx_req != NULL) { | ||
855 | list_add(&dev->current_rx_req->list, &dev->rx_reqs); | ||
856 | dev->current_rx_req = NULL; | ||
857 | } | ||
858 | dev->current_rx_bytes = 0; | ||
859 | dev->current_rx_buf = NULL; | ||
860 | dev->reset_printer = 1; | ||
861 | |||
862 | while (likely(!(list_empty(&dev->rx_buffers)))) { | ||
863 | req = container_of(dev->rx_buffers.next, struct usb_request, | ||
864 | list); | ||
865 | list_del_init(&req->list); | ||
866 | list_add(&req->list, &dev->rx_reqs); | ||
867 | } | ||
868 | |||
869 | while (likely(!(list_empty(&dev->rx_reqs_active)))) { | ||
870 | req = container_of(dev->rx_buffers.next, struct usb_request, | ||
871 | list); | ||
872 | list_del_init(&req->list); | ||
873 | list_add(&req->list, &dev->rx_reqs); | ||
874 | } | ||
875 | |||
876 | while (likely(!(list_empty(&dev->tx_reqs_active)))) { | ||
877 | req = container_of(dev->tx_reqs_active.next, | ||
878 | struct usb_request, list); | ||
879 | list_del_init(&req->list); | ||
880 | list_add(&req->list, &dev->tx_reqs); | ||
881 | } | ||
882 | |||
883 | if (usb_ep_enable(dev->in_ep)) | ||
884 | DBG(dev, "Failed to enable USB in_ep\n"); | ||
885 | if (usb_ep_enable(dev->out_ep)) | ||
886 | DBG(dev, "Failed to enable USB out_ep\n"); | ||
887 | |||
888 | wake_up_interruptible(&dev->rx_wait); | ||
889 | wake_up_interruptible(&dev->tx_wait); | ||
890 | wake_up_interruptible(&dev->tx_flush_wait); | ||
891 | } | ||
892 | |||
893 | /*-------------------------------------------------------------------------*/ | ||
894 | |||
895 | static bool gprinter_req_match(struct usb_function *f, | ||
896 | const struct usb_ctrlrequest *ctrl) | ||
897 | { | ||
898 | struct printer_dev *dev = func_to_printer(f); | ||
899 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
900 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
901 | u16 w_length = le16_to_cpu(ctrl->wLength); | ||
902 | |||
903 | if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE || | ||
904 | (ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) | ||
905 | return false; | ||
906 | |||
907 | switch (ctrl->bRequest) { | ||
908 | case GET_DEVICE_ID: | ||
909 | w_index >>= 8; | ||
910 | if (w_length <= PNP_STRING_LEN && | ||
911 | (USB_DIR_IN & ctrl->bRequestType)) | ||
912 | break; | ||
913 | return false; | ||
914 | case GET_PORT_STATUS: | ||
915 | if (!w_value && w_length == 1 && | ||
916 | (USB_DIR_IN & ctrl->bRequestType)) | ||
917 | break; | ||
918 | return false; | ||
919 | case SOFT_RESET: | ||
920 | if (!w_value && !w_length && | ||
921 | !(USB_DIR_IN & ctrl->bRequestType)) | ||
922 | break; | ||
923 | /* fall through */ | ||
924 | default: | ||
925 | return false; | ||
926 | } | ||
927 | return w_index == dev->interface; | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | * The setup() callback implements all the ep0 functionality that's not | ||
932 | * handled lower down. | ||
933 | */ | ||
934 | static int printer_func_setup(struct usb_function *f, | ||
935 | const struct usb_ctrlrequest *ctrl) | ||
936 | { | ||
937 | struct printer_dev *dev = func_to_printer(f); | ||
938 | struct usb_composite_dev *cdev = f->config->cdev; | ||
939 | struct usb_request *req = cdev->req; | ||
940 | int value = -EOPNOTSUPP; | ||
941 | u16 wIndex = le16_to_cpu(ctrl->wIndex); | ||
942 | u16 wValue = le16_to_cpu(ctrl->wValue); | ||
943 | u16 wLength = le16_to_cpu(ctrl->wLength); | ||
944 | |||
945 | DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n", | ||
946 | ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength); | ||
947 | |||
948 | switch (ctrl->bRequestType&USB_TYPE_MASK) { | ||
949 | case USB_TYPE_CLASS: | ||
950 | switch (ctrl->bRequest) { | ||
951 | case GET_DEVICE_ID: /* Get the IEEE-1284 PNP String */ | ||
952 | /* Only one printer interface is supported. */ | ||
953 | if ((wIndex>>8) != dev->interface) | ||
954 | break; | ||
955 | |||
956 | value = (dev->pnp_string[0] << 8) | dev->pnp_string[1]; | ||
957 | memcpy(req->buf, dev->pnp_string, value); | ||
958 | DBG(dev, "1284 PNP String: %x %s\n", value, | ||
959 | &dev->pnp_string[2]); | ||
960 | break; | ||
961 | |||
962 | case GET_PORT_STATUS: /* Get Port Status */ | ||
963 | /* Only one printer interface is supported. */ | ||
964 | if (wIndex != dev->interface) | ||
965 | break; | ||
966 | |||
967 | *(u8 *)req->buf = dev->printer_status; | ||
968 | value = min_t(u16, wLength, 1); | ||
969 | break; | ||
970 | |||
971 | case SOFT_RESET: /* Soft Reset */ | ||
972 | /* Only one printer interface is supported. */ | ||
973 | if (wIndex != dev->interface) | ||
974 | break; | ||
975 | |||
976 | printer_soft_reset(dev); | ||
977 | |||
978 | value = 0; | ||
979 | break; | ||
980 | |||
981 | default: | ||
982 | goto unknown; | ||
983 | } | ||
984 | break; | ||
985 | |||
986 | default: | ||
987 | unknown: | ||
988 | VDBG(dev, | ||
989 | "unknown ctrl req%02x.%02x v%04x i%04x l%d\n", | ||
990 | ctrl->bRequestType, ctrl->bRequest, | ||
991 | wValue, wIndex, wLength); | ||
992 | break; | ||
993 | } | ||
994 | /* host either stalls (value < 0) or reports success */ | ||
995 | if (value >= 0) { | ||
996 | req->length = value; | ||
997 | req->zero = value < wLength; | ||
998 | value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); | ||
999 | if (value < 0) { | ||
1000 | ERROR(dev, "%s:%d Error!\n", __func__, __LINE__); | ||
1001 | req->status = 0; | ||
1002 | } | ||
1003 | } | ||
1004 | return value; | ||
1005 | } | ||
1006 | |||
1007 | static int printer_func_bind(struct usb_configuration *c, | ||
1008 | struct usb_function *f) | ||
1009 | { | ||
1010 | struct usb_gadget *gadget = c->cdev->gadget; | ||
1011 | struct printer_dev *dev = func_to_printer(f); | ||
1012 | struct device *pdev; | ||
1013 | struct usb_composite_dev *cdev = c->cdev; | ||
1014 | struct usb_ep *in_ep; | ||
1015 | struct usb_ep *out_ep = NULL; | ||
1016 | struct usb_request *req; | ||
1017 | dev_t devt; | ||
1018 | int id; | ||
1019 | int ret; | ||
1020 | u32 i; | ||
1021 | |||
1022 | id = usb_interface_id(c, f); | ||
1023 | if (id < 0) | ||
1024 | return id; | ||
1025 | intf_desc.bInterfaceNumber = id; | ||
1026 | |||
1027 | /* finish hookup to lower layer ... */ | ||
1028 | dev->gadget = gadget; | ||
1029 | |||
1030 | /* all we really need is bulk IN/OUT */ | ||
1031 | in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc); | ||
1032 | if (!in_ep) { | ||
1033 | autoconf_fail: | ||
1034 | dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n", | ||
1035 | cdev->gadget->name); | ||
1036 | return -ENODEV; | ||
1037 | } | ||
1038 | in_ep->driver_data = in_ep; /* claim */ | ||
1039 | |||
1040 | out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc); | ||
1041 | if (!out_ep) | ||
1042 | goto autoconf_fail; | ||
1043 | out_ep->driver_data = out_ep; /* claim */ | ||
1044 | |||
1045 | /* assumes that all endpoints are dual-speed */ | ||
1046 | hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; | ||
1047 | hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; | ||
1048 | ss_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; | ||
1049 | ss_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; | ||
1050 | |||
1051 | ret = usb_assign_descriptors(f, fs_printer_function, | ||
1052 | hs_printer_function, ss_printer_function); | ||
1053 | if (ret) | ||
1054 | return ret; | ||
1055 | |||
1056 | dev->in_ep = in_ep; | ||
1057 | dev->out_ep = out_ep; | ||
1058 | |||
1059 | ret = -ENOMEM; | ||
1060 | for (i = 0; i < dev->q_len; i++) { | ||
1061 | req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL); | ||
1062 | if (!req) | ||
1063 | goto fail_tx_reqs; | ||
1064 | list_add(&req->list, &dev->tx_reqs); | ||
1065 | } | ||
1066 | |||
1067 | for (i = 0; i < dev->q_len; i++) { | ||
1068 | req = printer_req_alloc(dev->out_ep, USB_BUFSIZE, GFP_KERNEL); | ||
1069 | if (!req) | ||
1070 | goto fail_rx_reqs; | ||
1071 | list_add(&req->list, &dev->rx_reqs); | ||
1072 | } | ||
1073 | |||
1074 | /* Setup the sysfs files for the printer gadget. */ | ||
1075 | devt = MKDEV(major, dev->minor); | ||
1076 | pdev = device_create(usb_gadget_class, NULL, devt, | ||
1077 | NULL, "g_printer%d", dev->minor); | ||
1078 | if (IS_ERR(pdev)) { | ||
1079 | ERROR(dev, "Failed to create device: g_printer\n"); | ||
1080 | ret = PTR_ERR(pdev); | ||
1081 | goto fail_rx_reqs; | ||
1082 | } | ||
1083 | |||
1084 | /* | ||
1085 | * Register a character device as an interface to a user mode | ||
1086 | * program that handles the printer specific functionality. | ||
1087 | */ | ||
1088 | cdev_init(&dev->printer_cdev, &printer_io_operations); | ||
1089 | dev->printer_cdev.owner = THIS_MODULE; | ||
1090 | ret = cdev_add(&dev->printer_cdev, devt, 1); | ||
1091 | if (ret) { | ||
1092 | ERROR(dev, "Failed to open char device\n"); | ||
1093 | goto fail_cdev_add; | ||
1094 | } | ||
1095 | |||
1096 | return 0; | ||
1097 | |||
1098 | fail_cdev_add: | ||
1099 | device_destroy(usb_gadget_class, devt); | ||
1100 | |||
1101 | fail_rx_reqs: | ||
1102 | while (!list_empty(&dev->rx_reqs)) { | ||
1103 | req = container_of(dev->rx_reqs.next, struct usb_request, list); | ||
1104 | list_del(&req->list); | ||
1105 | printer_req_free(dev->out_ep, req); | ||
1106 | } | ||
1107 | |||
1108 | fail_tx_reqs: | ||
1109 | while (!list_empty(&dev->tx_reqs)) { | ||
1110 | req = container_of(dev->tx_reqs.next, struct usb_request, list); | ||
1111 | list_del(&req->list); | ||
1112 | printer_req_free(dev->in_ep, req); | ||
1113 | } | ||
1114 | |||
1115 | return ret; | ||
1116 | |||
1117 | } | ||
1118 | |||
1119 | static int printer_func_set_alt(struct usb_function *f, | ||
1120 | unsigned intf, unsigned alt) | ||
1121 | { | ||
1122 | struct printer_dev *dev = func_to_printer(f); | ||
1123 | int ret = -ENOTSUPP; | ||
1124 | |||
1125 | if (!alt) | ||
1126 | ret = set_interface(dev, intf); | ||
1127 | |||
1128 | return ret; | ||
1129 | } | ||
1130 | |||
1131 | static void printer_func_disable(struct usb_function *f) | ||
1132 | { | ||
1133 | struct printer_dev *dev = func_to_printer(f); | ||
1134 | unsigned long flags; | ||
1135 | |||
1136 | DBG(dev, "%s\n", __func__); | ||
1137 | |||
1138 | spin_lock_irqsave(&dev->lock, flags); | ||
1139 | printer_reset_interface(dev); | ||
1140 | spin_unlock_irqrestore(&dev->lock, flags); | ||
1141 | } | ||
1142 | |||
1143 | static inline struct f_printer_opts | ||
1144 | *to_f_printer_opts(struct config_item *item) | ||
1145 | { | ||
1146 | return container_of(to_config_group(item), struct f_printer_opts, | ||
1147 | func_inst.group); | ||
1148 | } | ||
1149 | |||
1150 | CONFIGFS_ATTR_STRUCT(f_printer_opts); | ||
1151 | CONFIGFS_ATTR_OPS(f_printer_opts); | ||
1152 | |||
1153 | static void printer_attr_release(struct config_item *item) | ||
1154 | { | ||
1155 | struct f_printer_opts *opts = to_f_printer_opts(item); | ||
1156 | |||
1157 | usb_put_function_instance(&opts->func_inst); | ||
1158 | } | ||
1159 | |||
1160 | static struct configfs_item_operations printer_item_ops = { | ||
1161 | .release = printer_attr_release, | ||
1162 | .show_attribute = f_printer_opts_attr_show, | ||
1163 | .store_attribute = f_printer_opts_attr_store, | ||
1164 | }; | ||
1165 | |||
1166 | static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts, | ||
1167 | char *page) | ||
1168 | { | ||
1169 | int result; | ||
1170 | |||
1171 | mutex_lock(&opts->lock); | ||
1172 | result = strlcpy(page, opts->pnp_string + 2, PNP_STRING_LEN - 2); | ||
1173 | mutex_unlock(&opts->lock); | ||
1174 | |||
1175 | return result; | ||
1176 | } | ||
1177 | |||
1178 | static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts, | ||
1179 | const char *page, size_t len) | ||
1180 | { | ||
1181 | int result, l; | ||
1182 | |||
1183 | mutex_lock(&opts->lock); | ||
1184 | result = strlcpy(opts->pnp_string + 2, page, PNP_STRING_LEN - 2); | ||
1185 | l = strlen(opts->pnp_string + 2) + 2; | ||
1186 | opts->pnp_string[0] = (l >> 8) & 0xFF; | ||
1187 | opts->pnp_string[1] = l & 0xFF; | ||
1188 | mutex_unlock(&opts->lock); | ||
1189 | |||
1190 | return result; | ||
1191 | } | ||
1192 | |||
1193 | static struct f_printer_opts_attribute f_printer_opts_pnp_string = | ||
1194 | __CONFIGFS_ATTR(pnp_string, S_IRUGO | S_IWUSR, | ||
1195 | f_printer_opts_pnp_string_show, | ||
1196 | f_printer_opts_pnp_string_store); | ||
1197 | |||
1198 | static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts, | ||
1199 | char *page) | ||
1200 | { | ||
1201 | int result; | ||
1202 | |||
1203 | mutex_lock(&opts->lock); | ||
1204 | result = sprintf(page, "%d\n", opts->q_len); | ||
1205 | mutex_unlock(&opts->lock); | ||
1206 | |||
1207 | return result; | ||
1208 | } | ||
1209 | |||
1210 | static ssize_t f_printer_opts_q_len_store(struct f_printer_opts *opts, | ||
1211 | const char *page, size_t len) | ||
1212 | { | ||
1213 | int ret; | ||
1214 | u16 num; | ||
1215 | |||
1216 | mutex_lock(&opts->lock); | ||
1217 | if (opts->refcnt) { | ||
1218 | ret = -EBUSY; | ||
1219 | goto end; | ||
1220 | } | ||
1221 | |||
1222 | ret = kstrtou16(page, 0, &num); | ||
1223 | if (ret) | ||
1224 | goto end; | ||
1225 | |||
1226 | opts->q_len = (unsigned)num; | ||
1227 | ret = len; | ||
1228 | end: | ||
1229 | mutex_unlock(&opts->lock); | ||
1230 | return ret; | ||
1231 | } | ||
1232 | |||
1233 | static struct f_printer_opts_attribute f_printer_opts_q_len = | ||
1234 | __CONFIGFS_ATTR(q_len, S_IRUGO | S_IWUSR, f_printer_opts_q_len_show, | ||
1235 | f_printer_opts_q_len_store); | ||
1236 | |||
1237 | static struct configfs_attribute *printer_attrs[] = { | ||
1238 | &f_printer_opts_pnp_string.attr, | ||
1239 | &f_printer_opts_q_len.attr, | ||
1240 | NULL, | ||
1241 | }; | ||
1242 | |||
1243 | static struct config_item_type printer_func_type = { | ||
1244 | .ct_item_ops = &printer_item_ops, | ||
1245 | .ct_attrs = printer_attrs, | ||
1246 | .ct_owner = THIS_MODULE, | ||
1247 | }; | ||
1248 | |||
1249 | static inline int gprinter_get_minor(void) | ||
1250 | { | ||
1251 | return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL); | ||
1252 | } | ||
1253 | |||
1254 | static inline void gprinter_put_minor(int minor) | ||
1255 | { | ||
1256 | ida_simple_remove(&printer_ida, minor); | ||
1257 | } | ||
1258 | |||
1259 | static int gprinter_setup(int); | ||
1260 | static void gprinter_cleanup(void); | ||
1261 | |||
1262 | static void gprinter_free_inst(struct usb_function_instance *f) | ||
1263 | { | ||
1264 | struct f_printer_opts *opts; | ||
1265 | |||
1266 | opts = container_of(f, struct f_printer_opts, func_inst); | ||
1267 | |||
1268 | mutex_lock(&printer_ida_lock); | ||
1269 | |||
1270 | gprinter_put_minor(opts->minor); | ||
1271 | if (idr_is_empty(&printer_ida.idr)) | ||
1272 | gprinter_cleanup(); | ||
1273 | |||
1274 | mutex_unlock(&printer_ida_lock); | ||
1275 | |||
1276 | kfree(opts); | ||
1277 | } | ||
1278 | |||
1279 | static struct usb_function_instance *gprinter_alloc_inst(void) | ||
1280 | { | ||
1281 | struct f_printer_opts *opts; | ||
1282 | struct usb_function_instance *ret; | ||
1283 | int status = 0; | ||
1284 | |||
1285 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
1286 | if (!opts) | ||
1287 | return ERR_PTR(-ENOMEM); | ||
1288 | |||
1289 | mutex_init(&opts->lock); | ||
1290 | opts->func_inst.free_func_inst = gprinter_free_inst; | ||
1291 | ret = &opts->func_inst; | ||
1292 | |||
1293 | mutex_lock(&printer_ida_lock); | ||
1294 | |||
1295 | if (idr_is_empty(&printer_ida.idr)) { | ||
1296 | status = gprinter_setup(PRINTER_MINORS); | ||
1297 | if (status) { | ||
1298 | ret = ERR_PTR(status); | ||
1299 | kfree(opts); | ||
1300 | goto unlock; | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | opts->minor = gprinter_get_minor(); | ||
1305 | if (opts->minor < 0) { | ||
1306 | ret = ERR_PTR(opts->minor); | ||
1307 | kfree(opts); | ||
1308 | if (idr_is_empty(&printer_ida.idr)) | ||
1309 | gprinter_cleanup(); | ||
1310 | goto unlock; | ||
1311 | } | ||
1312 | config_group_init_type_name(&opts->func_inst.group, "", | ||
1313 | &printer_func_type); | ||
1314 | |||
1315 | unlock: | ||
1316 | mutex_unlock(&printer_ida_lock); | ||
1317 | return ret; | ||
1318 | } | ||
1319 | |||
1320 | static void gprinter_free(struct usb_function *f) | ||
1321 | { | ||
1322 | struct printer_dev *dev = func_to_printer(f); | ||
1323 | struct f_printer_opts *opts; | ||
1324 | |||
1325 | opts = container_of(f->fi, struct f_printer_opts, func_inst); | ||
1326 | kfree(dev); | ||
1327 | mutex_lock(&opts->lock); | ||
1328 | --opts->refcnt; | ||
1329 | mutex_unlock(&opts->lock); | ||
1330 | } | ||
1331 | |||
1332 | static void printer_func_unbind(struct usb_configuration *c, | ||
1333 | struct usb_function *f) | ||
1334 | { | ||
1335 | struct printer_dev *dev; | ||
1336 | struct usb_request *req; | ||
1337 | |||
1338 | dev = func_to_printer(f); | ||
1339 | |||
1340 | device_destroy(usb_gadget_class, MKDEV(major, dev->minor)); | ||
1341 | |||
1342 | /* Remove Character Device */ | ||
1343 | cdev_del(&dev->printer_cdev); | ||
1344 | |||
1345 | /* we must already have been disconnected ... no i/o may be active */ | ||
1346 | WARN_ON(!list_empty(&dev->tx_reqs_active)); | ||
1347 | WARN_ON(!list_empty(&dev->rx_reqs_active)); | ||
1348 | |||
1349 | /* Free all memory for this driver. */ | ||
1350 | while (!list_empty(&dev->tx_reqs)) { | ||
1351 | req = container_of(dev->tx_reqs.next, struct usb_request, | ||
1352 | list); | ||
1353 | list_del(&req->list); | ||
1354 | printer_req_free(dev->in_ep, req); | ||
1355 | } | ||
1356 | |||
1357 | if (dev->current_rx_req != NULL) | ||
1358 | printer_req_free(dev->out_ep, dev->current_rx_req); | ||
1359 | |||
1360 | while (!list_empty(&dev->rx_reqs)) { | ||
1361 | req = container_of(dev->rx_reqs.next, | ||
1362 | struct usb_request, list); | ||
1363 | list_del(&req->list); | ||
1364 | printer_req_free(dev->out_ep, req); | ||
1365 | } | ||
1366 | |||
1367 | while (!list_empty(&dev->rx_buffers)) { | ||
1368 | req = container_of(dev->rx_buffers.next, | ||
1369 | struct usb_request, list); | ||
1370 | list_del(&req->list); | ||
1371 | printer_req_free(dev->out_ep, req); | ||
1372 | } | ||
1373 | usb_free_all_descriptors(f); | ||
1374 | } | ||
1375 | |||
1376 | static struct usb_function *gprinter_alloc(struct usb_function_instance *fi) | ||
1377 | { | ||
1378 | struct printer_dev *dev; | ||
1379 | struct f_printer_opts *opts; | ||
1380 | |||
1381 | opts = container_of(fi, struct f_printer_opts, func_inst); | ||
1382 | |||
1383 | mutex_lock(&opts->lock); | ||
1384 | if (opts->minor >= minors) { | ||
1385 | mutex_unlock(&opts->lock); | ||
1386 | return ERR_PTR(-ENOENT); | ||
1387 | } | ||
1388 | |||
1389 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1390 | if (!dev) { | ||
1391 | mutex_unlock(&opts->lock); | ||
1392 | return ERR_PTR(-ENOMEM); | ||
1393 | } | ||
1394 | |||
1395 | ++opts->refcnt; | ||
1396 | dev->minor = opts->minor; | ||
1397 | dev->pnp_string = opts->pnp_string; | ||
1398 | dev->q_len = opts->q_len; | ||
1399 | mutex_unlock(&opts->lock); | ||
1400 | |||
1401 | dev->function.name = "printer"; | ||
1402 | dev->function.bind = printer_func_bind; | ||
1403 | dev->function.setup = printer_func_setup; | ||
1404 | dev->function.unbind = printer_func_unbind; | ||
1405 | dev->function.set_alt = printer_func_set_alt; | ||
1406 | dev->function.disable = printer_func_disable; | ||
1407 | dev->function.req_match = gprinter_req_match; | ||
1408 | dev->function.free_func = gprinter_free; | ||
1409 | |||
1410 | INIT_LIST_HEAD(&dev->tx_reqs); | ||
1411 | INIT_LIST_HEAD(&dev->rx_reqs); | ||
1412 | INIT_LIST_HEAD(&dev->rx_buffers); | ||
1413 | INIT_LIST_HEAD(&dev->tx_reqs_active); | ||
1414 | INIT_LIST_HEAD(&dev->rx_reqs_active); | ||
1415 | |||
1416 | spin_lock_init(&dev->lock); | ||
1417 | mutex_init(&dev->lock_printer_io); | ||
1418 | init_waitqueue_head(&dev->rx_wait); | ||
1419 | init_waitqueue_head(&dev->tx_wait); | ||
1420 | init_waitqueue_head(&dev->tx_flush_wait); | ||
1421 | |||
1422 | dev->interface = -1; | ||
1423 | dev->printer_cdev_open = 0; | ||
1424 | dev->printer_status = PRINTER_NOT_ERROR; | ||
1425 | dev->current_rx_req = NULL; | ||
1426 | dev->current_rx_bytes = 0; | ||
1427 | dev->current_rx_buf = NULL; | ||
1428 | |||
1429 | return &dev->function; | ||
1430 | } | ||
1431 | |||
1432 | DECLARE_USB_FUNCTION_INIT(printer, gprinter_alloc_inst, gprinter_alloc); | ||
1433 | MODULE_LICENSE("GPL"); | ||
1434 | MODULE_AUTHOR("Craig Nadler"); | ||
1435 | |||
1436 | static int gprinter_setup(int count) | ||
1437 | { | ||
1438 | int status; | ||
1439 | dev_t devt; | ||
1440 | |||
1441 | usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget"); | ||
1442 | if (IS_ERR(usb_gadget_class)) { | ||
1443 | status = PTR_ERR(usb_gadget_class); | ||
1444 | usb_gadget_class = NULL; | ||
1445 | pr_err("unable to create usb_gadget class %d\n", status); | ||
1446 | return status; | ||
1447 | } | ||
1448 | |||
1449 | status = alloc_chrdev_region(&devt, 0, count, "USB printer gadget"); | ||
1450 | if (status) { | ||
1451 | pr_err("alloc_chrdev_region %d\n", status); | ||
1452 | class_destroy(usb_gadget_class); | ||
1453 | usb_gadget_class = NULL; | ||
1454 | return status; | ||
1455 | } | ||
1456 | |||
1457 | major = MAJOR(devt); | ||
1458 | minors = count; | ||
1459 | |||
1460 | return status; | ||
1461 | } | ||
1462 | |||
1463 | static void gprinter_cleanup(void) | ||
1464 | { | ||
1465 | if (major) { | ||
1466 | unregister_chrdev_region(MKDEV(major, 0), minors); | ||
1467 | major = minors = 0; | ||
1468 | } | ||
1469 | class_destroy(usb_gadget_class); | ||
1470 | usb_gadget_class = NULL; | ||
1471 | } | ||
diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index e07c50ced64d..3a5ae9900b1e 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c | |||
@@ -23,15 +23,6 @@ | |||
23 | #include "gadget_chips.h" | 23 | #include "gadget_chips.h" |
24 | #include "u_f.h" | 24 | #include "u_f.h" |
25 | 25 | ||
26 | #define USB_MS_TO_SS_INTERVAL(x) USB_MS_TO_HS_INTERVAL(x) | ||
27 | |||
28 | enum eptype { | ||
29 | EP_CONTROL = 0, | ||
30 | EP_BULK, | ||
31 | EP_ISOC, | ||
32 | EP_INTERRUPT, | ||
33 | }; | ||
34 | |||
35 | /* | 26 | /* |
36 | * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral | 27 | * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral |
37 | * controller drivers. | 28 | * controller drivers. |
@@ -64,8 +55,6 @@ struct f_sourcesink { | |||
64 | struct usb_ep *out_ep; | 55 | struct usb_ep *out_ep; |
65 | struct usb_ep *iso_in_ep; | 56 | struct usb_ep *iso_in_ep; |
66 | struct usb_ep *iso_out_ep; | 57 | struct usb_ep *iso_out_ep; |
67 | struct usb_ep *int_in_ep; | ||
68 | struct usb_ep *int_out_ep; | ||
69 | int cur_alt; | 58 | int cur_alt; |
70 | }; | 59 | }; |
71 | 60 | ||
@@ -79,10 +68,6 @@ static unsigned isoc_interval; | |||
79 | static unsigned isoc_maxpacket; | 68 | static unsigned isoc_maxpacket; |
80 | static unsigned isoc_mult; | 69 | static unsigned isoc_mult; |
81 | static unsigned isoc_maxburst; | 70 | static unsigned isoc_maxburst; |
82 | static unsigned int_interval; /* In ms */ | ||
83 | static unsigned int_maxpacket; | ||
84 | static unsigned int_mult; | ||
85 | static unsigned int_maxburst; | ||
86 | static unsigned buflen; | 71 | static unsigned buflen; |
87 | 72 | ||
88 | /*-------------------------------------------------------------------------*/ | 73 | /*-------------------------------------------------------------------------*/ |
@@ -107,16 +92,6 @@ static struct usb_interface_descriptor source_sink_intf_alt1 = { | |||
107 | /* .iInterface = DYNAMIC */ | 92 | /* .iInterface = DYNAMIC */ |
108 | }; | 93 | }; |
109 | 94 | ||
110 | static struct usb_interface_descriptor source_sink_intf_alt2 = { | ||
111 | .bLength = USB_DT_INTERFACE_SIZE, | ||
112 | .bDescriptorType = USB_DT_INTERFACE, | ||
113 | |||
114 | .bAlternateSetting = 2, | ||
115 | .bNumEndpoints = 2, | ||
116 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
117 | /* .iInterface = DYNAMIC */ | ||
118 | }; | ||
119 | |||
120 | /* full speed support: */ | 95 | /* full speed support: */ |
121 | 96 | ||
122 | static struct usb_endpoint_descriptor fs_source_desc = { | 97 | static struct usb_endpoint_descriptor fs_source_desc = { |
@@ -155,26 +130,6 @@ static struct usb_endpoint_descriptor fs_iso_sink_desc = { | |||
155 | .bInterval = 4, | 130 | .bInterval = 4, |
156 | }; | 131 | }; |
157 | 132 | ||
158 | static struct usb_endpoint_descriptor fs_int_source_desc = { | ||
159 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
160 | .bDescriptorType = USB_DT_ENDPOINT, | ||
161 | |||
162 | .bEndpointAddress = USB_DIR_IN, | ||
163 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
164 | .wMaxPacketSize = cpu_to_le16(64), | ||
165 | .bInterval = GZERO_INT_INTERVAL, | ||
166 | }; | ||
167 | |||
168 | static struct usb_endpoint_descriptor fs_int_sink_desc = { | ||
169 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
170 | .bDescriptorType = USB_DT_ENDPOINT, | ||
171 | |||
172 | .bEndpointAddress = USB_DIR_OUT, | ||
173 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
174 | .wMaxPacketSize = cpu_to_le16(64), | ||
175 | .bInterval = GZERO_INT_INTERVAL, | ||
176 | }; | ||
177 | |||
178 | static struct usb_descriptor_header *fs_source_sink_descs[] = { | 133 | static struct usb_descriptor_header *fs_source_sink_descs[] = { |
179 | (struct usb_descriptor_header *) &source_sink_intf_alt0, | 134 | (struct usb_descriptor_header *) &source_sink_intf_alt0, |
180 | (struct usb_descriptor_header *) &fs_sink_desc, | 135 | (struct usb_descriptor_header *) &fs_sink_desc, |
@@ -185,10 +140,6 @@ static struct usb_descriptor_header *fs_source_sink_descs[] = { | |||
185 | (struct usb_descriptor_header *) &fs_source_desc, | 140 | (struct usb_descriptor_header *) &fs_source_desc, |
186 | (struct usb_descriptor_header *) &fs_iso_sink_desc, | 141 | (struct usb_descriptor_header *) &fs_iso_sink_desc, |
187 | (struct usb_descriptor_header *) &fs_iso_source_desc, | 142 | (struct usb_descriptor_header *) &fs_iso_source_desc, |
188 | (struct usb_descriptor_header *) &source_sink_intf_alt2, | ||
189 | #define FS_ALT_IFC_2_OFFSET 8 | ||
190 | (struct usb_descriptor_header *) &fs_int_sink_desc, | ||
191 | (struct usb_descriptor_header *) &fs_int_source_desc, | ||
192 | NULL, | 143 | NULL, |
193 | }; | 144 | }; |
194 | 145 | ||
@@ -228,24 +179,6 @@ static struct usb_endpoint_descriptor hs_iso_sink_desc = { | |||
228 | .bInterval = 4, | 179 | .bInterval = 4, |
229 | }; | 180 | }; |
230 | 181 | ||
231 | static struct usb_endpoint_descriptor hs_int_source_desc = { | ||
232 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
233 | .bDescriptorType = USB_DT_ENDPOINT, | ||
234 | |||
235 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
236 | .wMaxPacketSize = cpu_to_le16(1024), | ||
237 | .bInterval = USB_MS_TO_HS_INTERVAL(GZERO_INT_INTERVAL), | ||
238 | }; | ||
239 | |||
240 | static struct usb_endpoint_descriptor hs_int_sink_desc = { | ||
241 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
242 | .bDescriptorType = USB_DT_ENDPOINT, | ||
243 | |||
244 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
245 | .wMaxPacketSize = cpu_to_le16(1024), | ||
246 | .bInterval = USB_MS_TO_HS_INTERVAL(GZERO_INT_INTERVAL), | ||
247 | }; | ||
248 | |||
249 | static struct usb_descriptor_header *hs_source_sink_descs[] = { | 182 | static struct usb_descriptor_header *hs_source_sink_descs[] = { |
250 | (struct usb_descriptor_header *) &source_sink_intf_alt0, | 183 | (struct usb_descriptor_header *) &source_sink_intf_alt0, |
251 | (struct usb_descriptor_header *) &hs_source_desc, | 184 | (struct usb_descriptor_header *) &hs_source_desc, |
@@ -256,10 +189,6 @@ static struct usb_descriptor_header *hs_source_sink_descs[] = { | |||
256 | (struct usb_descriptor_header *) &hs_sink_desc, | 189 | (struct usb_descriptor_header *) &hs_sink_desc, |
257 | (struct usb_descriptor_header *) &hs_iso_source_desc, | 190 | (struct usb_descriptor_header *) &hs_iso_source_desc, |
258 | (struct usb_descriptor_header *) &hs_iso_sink_desc, | 191 | (struct usb_descriptor_header *) &hs_iso_sink_desc, |
259 | (struct usb_descriptor_header *) &source_sink_intf_alt2, | ||
260 | #define HS_ALT_IFC_2_OFFSET 8 | ||
261 | (struct usb_descriptor_header *) &hs_int_source_desc, | ||
262 | (struct usb_descriptor_header *) &hs_int_sink_desc, | ||
263 | NULL, | 192 | NULL, |
264 | }; | 193 | }; |
265 | 194 | ||
@@ -335,42 +264,6 @@ static struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = { | |||
335 | .wBytesPerInterval = cpu_to_le16(1024), | 264 | .wBytesPerInterval = cpu_to_le16(1024), |
336 | }; | 265 | }; |
337 | 266 | ||
338 | static struct usb_endpoint_descriptor ss_int_source_desc = { | ||
339 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
340 | .bDescriptorType = USB_DT_ENDPOINT, | ||
341 | |||
342 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
343 | .wMaxPacketSize = cpu_to_le16(1024), | ||
344 | .bInterval = USB_MS_TO_SS_INTERVAL(GZERO_INT_INTERVAL), | ||
345 | }; | ||
346 | |||
347 | struct usb_ss_ep_comp_descriptor ss_int_source_comp_desc = { | ||
348 | .bLength = USB_DT_SS_EP_COMP_SIZE, | ||
349 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
350 | |||
351 | .bMaxBurst = 0, | ||
352 | .bmAttributes = 0, | ||
353 | .wBytesPerInterval = cpu_to_le16(1024), | ||
354 | }; | ||
355 | |||
356 | static struct usb_endpoint_descriptor ss_int_sink_desc = { | ||
357 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
358 | .bDescriptorType = USB_DT_ENDPOINT, | ||
359 | |||
360 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
361 | .wMaxPacketSize = cpu_to_le16(1024), | ||
362 | .bInterval = USB_MS_TO_SS_INTERVAL(GZERO_INT_INTERVAL), | ||
363 | }; | ||
364 | |||
365 | struct usb_ss_ep_comp_descriptor ss_int_sink_comp_desc = { | ||
366 | .bLength = USB_DT_SS_EP_COMP_SIZE, | ||
367 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
368 | |||
369 | .bMaxBurst = 0, | ||
370 | .bmAttributes = 0, | ||
371 | .wBytesPerInterval = cpu_to_le16(1024), | ||
372 | }; | ||
373 | |||
374 | static struct usb_descriptor_header *ss_source_sink_descs[] = { | 267 | static struct usb_descriptor_header *ss_source_sink_descs[] = { |
375 | (struct usb_descriptor_header *) &source_sink_intf_alt0, | 268 | (struct usb_descriptor_header *) &source_sink_intf_alt0, |
376 | (struct usb_descriptor_header *) &ss_source_desc, | 269 | (struct usb_descriptor_header *) &ss_source_desc, |
@@ -387,12 +280,6 @@ static struct usb_descriptor_header *ss_source_sink_descs[] = { | |||
387 | (struct usb_descriptor_header *) &ss_iso_source_comp_desc, | 280 | (struct usb_descriptor_header *) &ss_iso_source_comp_desc, |
388 | (struct usb_descriptor_header *) &ss_iso_sink_desc, | 281 | (struct usb_descriptor_header *) &ss_iso_sink_desc, |
389 | (struct usb_descriptor_header *) &ss_iso_sink_comp_desc, | 282 | (struct usb_descriptor_header *) &ss_iso_sink_comp_desc, |
390 | (struct usb_descriptor_header *) &source_sink_intf_alt2, | ||
391 | #define SS_ALT_IFC_2_OFFSET 14 | ||
392 | (struct usb_descriptor_header *) &ss_int_source_desc, | ||
393 | (struct usb_descriptor_header *) &ss_int_source_comp_desc, | ||
394 | (struct usb_descriptor_header *) &ss_int_sink_desc, | ||
395 | (struct usb_descriptor_header *) &ss_int_sink_comp_desc, | ||
396 | NULL, | 283 | NULL, |
397 | }; | 284 | }; |
398 | 285 | ||
@@ -414,21 +301,6 @@ static struct usb_gadget_strings *sourcesink_strings[] = { | |||
414 | }; | 301 | }; |
415 | 302 | ||
416 | /*-------------------------------------------------------------------------*/ | 303 | /*-------------------------------------------------------------------------*/ |
417 | static const char *get_ep_string(enum eptype ep_type) | ||
418 | { | ||
419 | switch (ep_type) { | ||
420 | case EP_ISOC: | ||
421 | return "ISOC-"; | ||
422 | case EP_INTERRUPT: | ||
423 | return "INTERRUPT-"; | ||
424 | case EP_CONTROL: | ||
425 | return "CTRL-"; | ||
426 | case EP_BULK: | ||
427 | return "BULK-"; | ||
428 | default: | ||
429 | return "UNKNOWN-"; | ||
430 | } | ||
431 | } | ||
432 | 304 | ||
433 | static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len) | 305 | static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len) |
434 | { | 306 | { |
@@ -456,8 +328,7 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) | |||
456 | 328 | ||
457 | void disable_endpoints(struct usb_composite_dev *cdev, | 329 | void disable_endpoints(struct usb_composite_dev *cdev, |
458 | struct usb_ep *in, struct usb_ep *out, | 330 | struct usb_ep *in, struct usb_ep *out, |
459 | struct usb_ep *iso_in, struct usb_ep *iso_out, | 331 | struct usb_ep *iso_in, struct usb_ep *iso_out) |
460 | struct usb_ep *int_in, struct usb_ep *int_out) | ||
461 | { | 332 | { |
462 | disable_ep(cdev, in); | 333 | disable_ep(cdev, in); |
463 | disable_ep(cdev, out); | 334 | disable_ep(cdev, out); |
@@ -465,10 +336,6 @@ void disable_endpoints(struct usb_composite_dev *cdev, | |||
465 | disable_ep(cdev, iso_in); | 336 | disable_ep(cdev, iso_in); |
466 | if (iso_out) | 337 | if (iso_out) |
467 | disable_ep(cdev, iso_out); | 338 | disable_ep(cdev, iso_out); |
468 | if (int_in) | ||
469 | disable_ep(cdev, int_in); | ||
470 | if (int_out) | ||
471 | disable_ep(cdev, int_out); | ||
472 | } | 339 | } |
473 | 340 | ||
474 | static int | 341 | static int |
@@ -485,7 +352,6 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) | |||
485 | return id; | 352 | return id; |
486 | source_sink_intf_alt0.bInterfaceNumber = id; | 353 | source_sink_intf_alt0.bInterfaceNumber = id; |
487 | source_sink_intf_alt1.bInterfaceNumber = id; | 354 | source_sink_intf_alt1.bInterfaceNumber = id; |
488 | source_sink_intf_alt2.bInterfaceNumber = id; | ||
489 | 355 | ||
490 | /* allocate bulk endpoints */ | 356 | /* allocate bulk endpoints */ |
491 | ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); | 357 | ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); |
@@ -546,55 +412,14 @@ no_iso: | |||
546 | if (isoc_maxpacket > 1024) | 412 | if (isoc_maxpacket > 1024) |
547 | isoc_maxpacket = 1024; | 413 | isoc_maxpacket = 1024; |
548 | 414 | ||
549 | /* sanity check the interrupt module parameters */ | ||
550 | if (int_interval < 1) | ||
551 | int_interval = 1; | ||
552 | if (int_interval > 4096) | ||
553 | int_interval = 4096; | ||
554 | if (int_mult > 2) | ||
555 | int_mult = 2; | ||
556 | if (int_maxburst > 15) | ||
557 | int_maxburst = 15; | ||
558 | |||
559 | /* fill in the FS interrupt descriptors from the module parameters */ | ||
560 | fs_int_source_desc.wMaxPacketSize = int_maxpacket > 64 ? | ||
561 | 64 : int_maxpacket; | ||
562 | fs_int_source_desc.bInterval = int_interval > 255 ? | ||
563 | 255 : int_interval; | ||
564 | fs_int_sink_desc.wMaxPacketSize = int_maxpacket > 64 ? | ||
565 | 64 : int_maxpacket; | ||
566 | fs_int_sink_desc.bInterval = int_interval > 255 ? | ||
567 | 255 : int_interval; | ||
568 | |||
569 | /* allocate int endpoints */ | ||
570 | ss->int_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_source_desc); | ||
571 | if (!ss->int_in_ep) | ||
572 | goto no_int; | ||
573 | ss->int_in_ep->driver_data = cdev; /* claim */ | ||
574 | |||
575 | ss->int_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_sink_desc); | ||
576 | if (ss->int_out_ep) { | ||
577 | ss->int_out_ep->driver_data = cdev; /* claim */ | ||
578 | } else { | ||
579 | ss->int_in_ep->driver_data = NULL; | ||
580 | ss->int_in_ep = NULL; | ||
581 | no_int: | ||
582 | fs_source_sink_descs[FS_ALT_IFC_2_OFFSET] = NULL; | ||
583 | hs_source_sink_descs[HS_ALT_IFC_2_OFFSET] = NULL; | ||
584 | ss_source_sink_descs[SS_ALT_IFC_2_OFFSET] = NULL; | ||
585 | } | ||
586 | |||
587 | if (int_maxpacket > 1024) | ||
588 | int_maxpacket = 1024; | ||
589 | |||
590 | /* support high speed hardware */ | 415 | /* support high speed hardware */ |
591 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; | 416 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; |
592 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; | 417 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; |
593 | 418 | ||
594 | /* | 419 | /* |
595 | * Fill in the HS isoc and interrupt descriptors from the module | 420 | * Fill in the HS isoc descriptors from the module parameters. |
596 | * parameters. We assume that the user knows what they are doing and | 421 | * We assume that the user knows what they are doing and won't |
597 | * won't give parameters that their UDC doesn't support. | 422 | * give parameters that their UDC doesn't support. |
598 | */ | 423 | */ |
599 | hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; | 424 | hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; |
600 | hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; | 425 | hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; |
@@ -607,17 +432,6 @@ no_int: | |||
607 | hs_iso_sink_desc.bInterval = isoc_interval; | 432 | hs_iso_sink_desc.bInterval = isoc_interval; |
608 | hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; | 433 | hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; |
609 | 434 | ||
610 | hs_int_source_desc.wMaxPacketSize = int_maxpacket; | ||
611 | hs_int_source_desc.wMaxPacketSize |= int_mult << 11; | ||
612 | hs_int_source_desc.bInterval = USB_MS_TO_HS_INTERVAL(int_interval); | ||
613 | hs_int_source_desc.bEndpointAddress = | ||
614 | fs_int_source_desc.bEndpointAddress; | ||
615 | |||
616 | hs_int_sink_desc.wMaxPacketSize = int_maxpacket; | ||
617 | hs_int_sink_desc.wMaxPacketSize |= int_mult << 11; | ||
618 | hs_int_sink_desc.bInterval = USB_MS_TO_HS_INTERVAL(int_interval); | ||
619 | hs_int_sink_desc.bEndpointAddress = fs_int_sink_desc.bEndpointAddress; | ||
620 | |||
621 | /* support super speed hardware */ | 435 | /* support super speed hardware */ |
622 | ss_source_desc.bEndpointAddress = | 436 | ss_source_desc.bEndpointAddress = |
623 | fs_source_desc.bEndpointAddress; | 437 | fs_source_desc.bEndpointAddress; |
@@ -625,9 +439,9 @@ no_int: | |||
625 | fs_sink_desc.bEndpointAddress; | 439 | fs_sink_desc.bEndpointAddress; |
626 | 440 | ||
627 | /* | 441 | /* |
628 | * Fill in the SS isoc and interrupt descriptors from the module | 442 | * Fill in the SS isoc descriptors from the module parameters. |
629 | * parameters. We assume that the user knows what they are doing and | 443 | * We assume that the user knows what they are doing and won't |
630 | * won't give parameters that their UDC doesn't support. | 444 | * give parameters that their UDC doesn't support. |
631 | */ | 445 | */ |
632 | ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; | 446 | ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; |
633 | ss_iso_source_desc.bInterval = isoc_interval; | 447 | ss_iso_source_desc.bInterval = isoc_interval; |
@@ -646,37 +460,17 @@ no_int: | |||
646 | isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); | 460 | isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); |
647 | ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; | 461 | ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; |
648 | 462 | ||
649 | ss_int_source_desc.wMaxPacketSize = int_maxpacket; | ||
650 | ss_int_source_desc.bInterval = USB_MS_TO_SS_INTERVAL(int_interval); | ||
651 | ss_int_source_comp_desc.bmAttributes = int_mult; | ||
652 | ss_int_source_comp_desc.bMaxBurst = int_maxburst; | ||
653 | ss_int_source_comp_desc.wBytesPerInterval = | ||
654 | int_maxpacket * (int_mult + 1) * (int_maxburst + 1); | ||
655 | ss_int_source_desc.bEndpointAddress = | ||
656 | fs_int_source_desc.bEndpointAddress; | ||
657 | |||
658 | ss_int_sink_desc.wMaxPacketSize = int_maxpacket; | ||
659 | ss_int_sink_desc.bInterval = USB_MS_TO_SS_INTERVAL(int_interval); | ||
660 | ss_int_sink_comp_desc.bmAttributes = int_mult; | ||
661 | ss_int_sink_comp_desc.bMaxBurst = int_maxburst; | ||
662 | ss_int_sink_comp_desc.wBytesPerInterval = | ||
663 | int_maxpacket * (int_mult + 1) * (int_maxburst + 1); | ||
664 | ss_int_sink_desc.bEndpointAddress = fs_int_sink_desc.bEndpointAddress; | ||
665 | |||
666 | ret = usb_assign_descriptors(f, fs_source_sink_descs, | 463 | ret = usb_assign_descriptors(f, fs_source_sink_descs, |
667 | hs_source_sink_descs, ss_source_sink_descs); | 464 | hs_source_sink_descs, ss_source_sink_descs); |
668 | if (ret) | 465 | if (ret) |
669 | return ret; | 466 | return ret; |
670 | 467 | ||
671 | DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s, " | 468 | DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n", |
672 | "INT-IN/%s, INT-OUT/%s\n", | ||
673 | (gadget_is_superspeed(c->cdev->gadget) ? "super" : | 469 | (gadget_is_superspeed(c->cdev->gadget) ? "super" : |
674 | (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), | 470 | (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), |
675 | f->name, ss->in_ep->name, ss->out_ep->name, | 471 | f->name, ss->in_ep->name, ss->out_ep->name, |
676 | ss->iso_in_ep ? ss->iso_in_ep->name : "<none>", | 472 | ss->iso_in_ep ? ss->iso_in_ep->name : "<none>", |
677 | ss->iso_out_ep ? ss->iso_out_ep->name : "<none>", | 473 | ss->iso_out_ep ? ss->iso_out_ep->name : "<none>"); |
678 | ss->int_in_ep ? ss->int_in_ep->name : "<none>", | ||
679 | ss->int_out_ep ? ss->int_out_ep->name : "<none>"); | ||
680 | return 0; | 474 | return 0; |
681 | } | 475 | } |
682 | 476 | ||
@@ -807,15 +601,14 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) | |||
807 | } | 601 | } |
808 | 602 | ||
809 | static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, | 603 | static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, |
810 | enum eptype ep_type, int speed) | 604 | bool is_iso, int speed) |
811 | { | 605 | { |
812 | struct usb_ep *ep; | 606 | struct usb_ep *ep; |
813 | struct usb_request *req; | 607 | struct usb_request *req; |
814 | int i, size, status; | 608 | int i, size, status; |
815 | 609 | ||
816 | for (i = 0; i < 8; i++) { | 610 | for (i = 0; i < 8; i++) { |
817 | switch (ep_type) { | 611 | if (is_iso) { |
818 | case EP_ISOC: | ||
819 | switch (speed) { | 612 | switch (speed) { |
820 | case USB_SPEED_SUPER: | 613 | case USB_SPEED_SUPER: |
821 | size = isoc_maxpacket * (isoc_mult + 1) * | 614 | size = isoc_maxpacket * (isoc_mult + 1) * |
@@ -831,28 +624,9 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, | |||
831 | } | 624 | } |
832 | ep = is_in ? ss->iso_in_ep : ss->iso_out_ep; | 625 | ep = is_in ? ss->iso_in_ep : ss->iso_out_ep; |
833 | req = ss_alloc_ep_req(ep, size); | 626 | req = ss_alloc_ep_req(ep, size); |
834 | break; | 627 | } else { |
835 | case EP_INTERRUPT: | ||
836 | switch (speed) { | ||
837 | case USB_SPEED_SUPER: | ||
838 | size = int_maxpacket * (int_mult + 1) * | ||
839 | (int_maxburst + 1); | ||
840 | break; | ||
841 | case USB_SPEED_HIGH: | ||
842 | size = int_maxpacket * (int_mult + 1); | ||
843 | break; | ||
844 | default: | ||
845 | size = int_maxpacket > 1023 ? | ||
846 | 1023 : int_maxpacket; | ||
847 | break; | ||
848 | } | ||
849 | ep = is_in ? ss->int_in_ep : ss->int_out_ep; | ||
850 | req = ss_alloc_ep_req(ep, size); | ||
851 | break; | ||
852 | default: | ||
853 | ep = is_in ? ss->in_ep : ss->out_ep; | 628 | ep = is_in ? ss->in_ep : ss->out_ep; |
854 | req = ss_alloc_ep_req(ep, 0); | 629 | req = ss_alloc_ep_req(ep, 0); |
855 | break; | ||
856 | } | 630 | } |
857 | 631 | ||
858 | if (!req) | 632 | if (!req) |
@@ -870,12 +644,12 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, | |||
870 | 644 | ||
871 | cdev = ss->function.config->cdev; | 645 | cdev = ss->function.config->cdev; |
872 | ERROR(cdev, "start %s%s %s --> %d\n", | 646 | ERROR(cdev, "start %s%s %s --> %d\n", |
873 | get_ep_string(ep_type), is_in ? "IN" : "OUT", | 647 | is_iso ? "ISO-" : "", is_in ? "IN" : "OUT", |
874 | ep->name, status); | 648 | ep->name, status); |
875 | free_ep_req(ep, req); | 649 | free_ep_req(ep, req); |
876 | } | 650 | } |
877 | 651 | ||
878 | if (!(ep_type == EP_ISOC)) | 652 | if (!is_iso) |
879 | break; | 653 | break; |
880 | } | 654 | } |
881 | 655 | ||
@@ -888,7 +662,7 @@ static void disable_source_sink(struct f_sourcesink *ss) | |||
888 | 662 | ||
889 | cdev = ss->function.config->cdev; | 663 | cdev = ss->function.config->cdev; |
890 | disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep, | 664 | disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep, |
891 | ss->iso_out_ep, ss->int_in_ep, ss->int_out_ep); | 665 | ss->iso_out_ep); |
892 | VDBG(cdev, "%s disabled\n", ss->function.name); | 666 | VDBG(cdev, "%s disabled\n", ss->function.name); |
893 | } | 667 | } |
894 | 668 | ||
@@ -900,62 +674,6 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss, | |||
900 | int speed = cdev->gadget->speed; | 674 | int speed = cdev->gadget->speed; |
901 | struct usb_ep *ep; | 675 | struct usb_ep *ep; |
902 | 676 | ||
903 | if (alt == 2) { | ||
904 | /* Configure for periodic interrupt endpoint */ | ||
905 | ep = ss->int_in_ep; | ||
906 | if (ep) { | ||
907 | result = config_ep_by_speed(cdev->gadget, | ||
908 | &(ss->function), ep); | ||
909 | if (result) | ||
910 | return result; | ||
911 | |||
912 | result = usb_ep_enable(ep); | ||
913 | if (result < 0) | ||
914 | return result; | ||
915 | |||
916 | ep->driver_data = ss; | ||
917 | result = source_sink_start_ep(ss, true, EP_INTERRUPT, | ||
918 | speed); | ||
919 | if (result < 0) { | ||
920 | fail1: | ||
921 | ep = ss->int_in_ep; | ||
922 | if (ep) { | ||
923 | usb_ep_disable(ep); | ||
924 | ep->driver_data = NULL; | ||
925 | } | ||
926 | return result; | ||
927 | } | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | * one interrupt endpoint reads (sinks) anything OUT (from the | ||
932 | * host) | ||
933 | */ | ||
934 | ep = ss->int_out_ep; | ||
935 | if (ep) { | ||
936 | result = config_ep_by_speed(cdev->gadget, | ||
937 | &(ss->function), ep); | ||
938 | if (result) | ||
939 | goto fail1; | ||
940 | |||
941 | result = usb_ep_enable(ep); | ||
942 | if (result < 0) | ||
943 | goto fail1; | ||
944 | |||
945 | ep->driver_data = ss; | ||
946 | result = source_sink_start_ep(ss, false, EP_INTERRUPT, | ||
947 | speed); | ||
948 | if (result < 0) { | ||
949 | ep = ss->int_out_ep; | ||
950 | usb_ep_disable(ep); | ||
951 | ep->driver_data = NULL; | ||
952 | goto fail1; | ||
953 | } | ||
954 | } | ||
955 | |||
956 | goto out; | ||
957 | } | ||
958 | |||
959 | /* one bulk endpoint writes (sources) zeroes IN (to the host) */ | 677 | /* one bulk endpoint writes (sources) zeroes IN (to the host) */ |
960 | ep = ss->in_ep; | 678 | ep = ss->in_ep; |
961 | result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); | 679 | result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); |
@@ -966,7 +684,7 @@ fail1: | |||
966 | return result; | 684 | return result; |
967 | ep->driver_data = ss; | 685 | ep->driver_data = ss; |
968 | 686 | ||
969 | result = source_sink_start_ep(ss, true, EP_BULK, speed); | 687 | result = source_sink_start_ep(ss, true, false, speed); |
970 | if (result < 0) { | 688 | if (result < 0) { |
971 | fail: | 689 | fail: |
972 | ep = ss->in_ep; | 690 | ep = ss->in_ep; |
@@ -985,7 +703,7 @@ fail: | |||
985 | goto fail; | 703 | goto fail; |
986 | ep->driver_data = ss; | 704 | ep->driver_data = ss; |
987 | 705 | ||
988 | result = source_sink_start_ep(ss, false, EP_BULK, speed); | 706 | result = source_sink_start_ep(ss, false, false, speed); |
989 | if (result < 0) { | 707 | if (result < 0) { |
990 | fail2: | 708 | fail2: |
991 | ep = ss->out_ep; | 709 | ep = ss->out_ep; |
@@ -1008,7 +726,7 @@ fail2: | |||
1008 | goto fail2; | 726 | goto fail2; |
1009 | ep->driver_data = ss; | 727 | ep->driver_data = ss; |
1010 | 728 | ||
1011 | result = source_sink_start_ep(ss, true, EP_ISOC, speed); | 729 | result = source_sink_start_ep(ss, true, true, speed); |
1012 | if (result < 0) { | 730 | if (result < 0) { |
1013 | fail3: | 731 | fail3: |
1014 | ep = ss->iso_in_ep; | 732 | ep = ss->iso_in_ep; |
@@ -1031,14 +749,13 @@ fail3: | |||
1031 | goto fail3; | 749 | goto fail3; |
1032 | ep->driver_data = ss; | 750 | ep->driver_data = ss; |
1033 | 751 | ||
1034 | result = source_sink_start_ep(ss, false, EP_ISOC, speed); | 752 | result = source_sink_start_ep(ss, false, true, speed); |
1035 | if (result < 0) { | 753 | if (result < 0) { |
1036 | usb_ep_disable(ep); | 754 | usb_ep_disable(ep); |
1037 | ep->driver_data = NULL; | 755 | ep->driver_data = NULL; |
1038 | goto fail3; | 756 | goto fail3; |
1039 | } | 757 | } |
1040 | } | 758 | } |
1041 | |||
1042 | out: | 759 | out: |
1043 | ss->cur_alt = alt; | 760 | ss->cur_alt = alt; |
1044 | 761 | ||
@@ -1054,8 +771,6 @@ static int sourcesink_set_alt(struct usb_function *f, | |||
1054 | 771 | ||
1055 | if (ss->in_ep->driver_data) | 772 | if (ss->in_ep->driver_data) |
1056 | disable_source_sink(ss); | 773 | disable_source_sink(ss); |
1057 | else if (alt == 2 && ss->int_in_ep->driver_data) | ||
1058 | disable_source_sink(ss); | ||
1059 | return enable_source_sink(cdev, ss, alt); | 774 | return enable_source_sink(cdev, ss, alt); |
1060 | } | 775 | } |
1061 | 776 | ||
@@ -1168,10 +883,6 @@ static struct usb_function *source_sink_alloc_func( | |||
1168 | isoc_maxpacket = ss_opts->isoc_maxpacket; | 883 | isoc_maxpacket = ss_opts->isoc_maxpacket; |
1169 | isoc_mult = ss_opts->isoc_mult; | 884 | isoc_mult = ss_opts->isoc_mult; |
1170 | isoc_maxburst = ss_opts->isoc_maxburst; | 885 | isoc_maxburst = ss_opts->isoc_maxburst; |
1171 | int_interval = ss_opts->int_interval; | ||
1172 | int_maxpacket = ss_opts->int_maxpacket; | ||
1173 | int_mult = ss_opts->int_mult; | ||
1174 | int_maxburst = ss_opts->int_maxburst; | ||
1175 | buflen = ss_opts->bulk_buflen; | 886 | buflen = ss_opts->bulk_buflen; |
1176 | 887 | ||
1177 | ss->function.name = "source/sink"; | 888 | ss->function.name = "source/sink"; |
@@ -1468,182 +1179,6 @@ static struct f_ss_opts_attribute f_ss_opts_bulk_buflen = | |||
1468 | f_ss_opts_bulk_buflen_show, | 1179 | f_ss_opts_bulk_buflen_show, |
1469 | f_ss_opts_bulk_buflen_store); | 1180 | f_ss_opts_bulk_buflen_store); |
1470 | 1181 | ||
1471 | static ssize_t f_ss_opts_int_interval_show(struct f_ss_opts *opts, char *page) | ||
1472 | { | ||
1473 | int result; | ||
1474 | |||
1475 | mutex_lock(&opts->lock); | ||
1476 | result = sprintf(page, "%u", opts->int_interval); | ||
1477 | mutex_unlock(&opts->lock); | ||
1478 | |||
1479 | return result; | ||
1480 | } | ||
1481 | |||
1482 | static ssize_t f_ss_opts_int_interval_store(struct f_ss_opts *opts, | ||
1483 | const char *page, size_t len) | ||
1484 | { | ||
1485 | int ret; | ||
1486 | u32 num; | ||
1487 | |||
1488 | mutex_lock(&opts->lock); | ||
1489 | if (opts->refcnt) { | ||
1490 | ret = -EBUSY; | ||
1491 | goto end; | ||
1492 | } | ||
1493 | |||
1494 | ret = kstrtou32(page, 0, &num); | ||
1495 | if (ret) | ||
1496 | goto end; | ||
1497 | |||
1498 | if (num > 4096) { | ||
1499 | ret = -EINVAL; | ||
1500 | goto end; | ||
1501 | } | ||
1502 | |||
1503 | opts->int_interval = num; | ||
1504 | ret = len; | ||
1505 | end: | ||
1506 | mutex_unlock(&opts->lock); | ||
1507 | return ret; | ||
1508 | } | ||
1509 | |||
1510 | static struct f_ss_opts_attribute f_ss_opts_int_interval = | ||
1511 | __CONFIGFS_ATTR(int_interval, S_IRUGO | S_IWUSR, | ||
1512 | f_ss_opts_int_interval_show, | ||
1513 | f_ss_opts_int_interval_store); | ||
1514 | |||
1515 | static ssize_t f_ss_opts_int_maxpacket_show(struct f_ss_opts *opts, char *page) | ||
1516 | { | ||
1517 | int result; | ||
1518 | |||
1519 | mutex_lock(&opts->lock); | ||
1520 | result = sprintf(page, "%u", opts->int_maxpacket); | ||
1521 | mutex_unlock(&opts->lock); | ||
1522 | |||
1523 | return result; | ||
1524 | } | ||
1525 | |||
1526 | static ssize_t f_ss_opts_int_maxpacket_store(struct f_ss_opts *opts, | ||
1527 | const char *page, size_t len) | ||
1528 | { | ||
1529 | int ret; | ||
1530 | u16 num; | ||
1531 | |||
1532 | mutex_lock(&opts->lock); | ||
1533 | if (opts->refcnt) { | ||
1534 | ret = -EBUSY; | ||
1535 | goto end; | ||
1536 | } | ||
1537 | |||
1538 | ret = kstrtou16(page, 0, &num); | ||
1539 | if (ret) | ||
1540 | goto end; | ||
1541 | |||
1542 | if (num > 1024) { | ||
1543 | ret = -EINVAL; | ||
1544 | goto end; | ||
1545 | } | ||
1546 | |||
1547 | opts->int_maxpacket = num; | ||
1548 | ret = len; | ||
1549 | end: | ||
1550 | mutex_unlock(&opts->lock); | ||
1551 | return ret; | ||
1552 | } | ||
1553 | |||
1554 | static struct f_ss_opts_attribute f_ss_opts_int_maxpacket = | ||
1555 | __CONFIGFS_ATTR(int_maxpacket, S_IRUGO | S_IWUSR, | ||
1556 | f_ss_opts_int_maxpacket_show, | ||
1557 | f_ss_opts_int_maxpacket_store); | ||
1558 | |||
1559 | static ssize_t f_ss_opts_int_mult_show(struct f_ss_opts *opts, char *page) | ||
1560 | { | ||
1561 | int result; | ||
1562 | |||
1563 | mutex_lock(&opts->lock); | ||
1564 | result = sprintf(page, "%u", opts->int_mult); | ||
1565 | mutex_unlock(&opts->lock); | ||
1566 | |||
1567 | return result; | ||
1568 | } | ||
1569 | |||
1570 | static ssize_t f_ss_opts_int_mult_store(struct f_ss_opts *opts, | ||
1571 | const char *page, size_t len) | ||
1572 | { | ||
1573 | int ret; | ||
1574 | u8 num; | ||
1575 | |||
1576 | mutex_lock(&opts->lock); | ||
1577 | if (opts->refcnt) { | ||
1578 | ret = -EBUSY; | ||
1579 | goto end; | ||
1580 | } | ||
1581 | |||
1582 | ret = kstrtou8(page, 0, &num); | ||
1583 | if (ret) | ||
1584 | goto end; | ||
1585 | |||
1586 | if (num > 2) { | ||
1587 | ret = -EINVAL; | ||
1588 | goto end; | ||
1589 | } | ||
1590 | |||
1591 | opts->int_mult = num; | ||
1592 | ret = len; | ||
1593 | end: | ||
1594 | mutex_unlock(&opts->lock); | ||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | static struct f_ss_opts_attribute f_ss_opts_int_mult = | ||
1599 | __CONFIGFS_ATTR(int_mult, S_IRUGO | S_IWUSR, | ||
1600 | f_ss_opts_int_mult_show, | ||
1601 | f_ss_opts_int_mult_store); | ||
1602 | |||
1603 | static ssize_t f_ss_opts_int_maxburst_show(struct f_ss_opts *opts, char *page) | ||
1604 | { | ||
1605 | int result; | ||
1606 | |||
1607 | mutex_lock(&opts->lock); | ||
1608 | result = sprintf(page, "%u", opts->int_maxburst); | ||
1609 | mutex_unlock(&opts->lock); | ||
1610 | |||
1611 | return result; | ||
1612 | } | ||
1613 | |||
1614 | static ssize_t f_ss_opts_int_maxburst_store(struct f_ss_opts *opts, | ||
1615 | const char *page, size_t len) | ||
1616 | { | ||
1617 | int ret; | ||
1618 | u8 num; | ||
1619 | |||
1620 | mutex_lock(&opts->lock); | ||
1621 | if (opts->refcnt) { | ||
1622 | ret = -EBUSY; | ||
1623 | goto end; | ||
1624 | } | ||
1625 | |||
1626 | ret = kstrtou8(page, 0, &num); | ||
1627 | if (ret) | ||
1628 | goto end; | ||
1629 | |||
1630 | if (num > 15) { | ||
1631 | ret = -EINVAL; | ||
1632 | goto end; | ||
1633 | } | ||
1634 | |||
1635 | opts->int_maxburst = num; | ||
1636 | ret = len; | ||
1637 | end: | ||
1638 | mutex_unlock(&opts->lock); | ||
1639 | return ret; | ||
1640 | } | ||
1641 | |||
1642 | static struct f_ss_opts_attribute f_ss_opts_int_maxburst = | ||
1643 | __CONFIGFS_ATTR(int_maxburst, S_IRUGO | S_IWUSR, | ||
1644 | f_ss_opts_int_maxburst_show, | ||
1645 | f_ss_opts_int_maxburst_store); | ||
1646 | |||
1647 | static struct configfs_attribute *ss_attrs[] = { | 1182 | static struct configfs_attribute *ss_attrs[] = { |
1648 | &f_ss_opts_pattern.attr, | 1183 | &f_ss_opts_pattern.attr, |
1649 | &f_ss_opts_isoc_interval.attr, | 1184 | &f_ss_opts_isoc_interval.attr, |
@@ -1651,10 +1186,6 @@ static struct configfs_attribute *ss_attrs[] = { | |||
1651 | &f_ss_opts_isoc_mult.attr, | 1186 | &f_ss_opts_isoc_mult.attr, |
1652 | &f_ss_opts_isoc_maxburst.attr, | 1187 | &f_ss_opts_isoc_maxburst.attr, |
1653 | &f_ss_opts_bulk_buflen.attr, | 1188 | &f_ss_opts_bulk_buflen.attr, |
1654 | &f_ss_opts_int_interval.attr, | ||
1655 | &f_ss_opts_int_maxpacket.attr, | ||
1656 | &f_ss_opts_int_mult.attr, | ||
1657 | &f_ss_opts_int_maxburst.attr, | ||
1658 | NULL, | 1189 | NULL, |
1659 | }; | 1190 | }; |
1660 | 1191 | ||
@@ -1684,8 +1215,6 @@ static struct usb_function_instance *source_sink_alloc_inst(void) | |||
1684 | ss_opts->isoc_interval = GZERO_ISOC_INTERVAL; | 1215 | ss_opts->isoc_interval = GZERO_ISOC_INTERVAL; |
1685 | ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET; | 1216 | ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET; |
1686 | ss_opts->bulk_buflen = GZERO_BULK_BUFLEN; | 1217 | ss_opts->bulk_buflen = GZERO_BULK_BUFLEN; |
1687 | ss_opts->int_interval = GZERO_INT_INTERVAL; | ||
1688 | ss_opts->int_maxpacket = GZERO_INT_MAXPACKET; | ||
1689 | 1218 | ||
1690 | config_group_init_type_name(&ss_opts->func_inst.group, "", | 1219 | config_group_init_type_name(&ss_opts->func_inst.group, "", |
1691 | &ss_func_type); | 1220 | &ss_func_type); |
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 33e16658e5cf..6d3eb8b00a48 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #define UNFLW_CTRL 8 | 54 | #define UNFLW_CTRL 8 |
55 | #define OVFLW_CTRL 10 | 55 | #define OVFLW_CTRL 10 |
56 | 56 | ||
57 | const char *uac2_name = "snd_uac2"; | 57 | static const char *uac2_name = "snd_uac2"; |
58 | 58 | ||
59 | struct uac2_req { | 59 | struct uac2_req { |
60 | struct uac2_rtd_params *pp; /* parent param */ | 60 | struct uac2_rtd_params *pp; /* parent param */ |
@@ -634,7 +634,7 @@ static struct usb_interface_descriptor std_ac_if_desc = { | |||
634 | }; | 634 | }; |
635 | 635 | ||
636 | /* Clock source for IN traffic */ | 636 | /* Clock source for IN traffic */ |
637 | struct uac_clock_source_descriptor in_clk_src_desc = { | 637 | static struct uac_clock_source_descriptor in_clk_src_desc = { |
638 | .bLength = sizeof in_clk_src_desc, | 638 | .bLength = sizeof in_clk_src_desc, |
639 | .bDescriptorType = USB_DT_CS_INTERFACE, | 639 | .bDescriptorType = USB_DT_CS_INTERFACE, |
640 | 640 | ||
@@ -646,7 +646,7 @@ struct uac_clock_source_descriptor in_clk_src_desc = { | |||
646 | }; | 646 | }; |
647 | 647 | ||
648 | /* Clock source for OUT traffic */ | 648 | /* Clock source for OUT traffic */ |
649 | struct uac_clock_source_descriptor out_clk_src_desc = { | 649 | static struct uac_clock_source_descriptor out_clk_src_desc = { |
650 | .bLength = sizeof out_clk_src_desc, | 650 | .bLength = sizeof out_clk_src_desc, |
651 | .bDescriptorType = USB_DT_CS_INTERFACE, | 651 | .bDescriptorType = USB_DT_CS_INTERFACE, |
652 | 652 | ||
@@ -658,7 +658,7 @@ struct uac_clock_source_descriptor out_clk_src_desc = { | |||
658 | }; | 658 | }; |
659 | 659 | ||
660 | /* Input Terminal for USB_OUT */ | 660 | /* Input Terminal for USB_OUT */ |
661 | struct uac2_input_terminal_descriptor usb_out_it_desc = { | 661 | static struct uac2_input_terminal_descriptor usb_out_it_desc = { |
662 | .bLength = sizeof usb_out_it_desc, | 662 | .bLength = sizeof usb_out_it_desc, |
663 | .bDescriptorType = USB_DT_CS_INTERFACE, | 663 | .bDescriptorType = USB_DT_CS_INTERFACE, |
664 | 664 | ||
@@ -672,7 +672,7 @@ struct uac2_input_terminal_descriptor usb_out_it_desc = { | |||
672 | }; | 672 | }; |
673 | 673 | ||
674 | /* Input Terminal for I/O-In */ | 674 | /* Input Terminal for I/O-In */ |
675 | struct uac2_input_terminal_descriptor io_in_it_desc = { | 675 | static struct uac2_input_terminal_descriptor io_in_it_desc = { |
676 | .bLength = sizeof io_in_it_desc, | 676 | .bLength = sizeof io_in_it_desc, |
677 | .bDescriptorType = USB_DT_CS_INTERFACE, | 677 | .bDescriptorType = USB_DT_CS_INTERFACE, |
678 | 678 | ||
@@ -686,7 +686,7 @@ struct uac2_input_terminal_descriptor io_in_it_desc = { | |||
686 | }; | 686 | }; |
687 | 687 | ||
688 | /* Ouput Terminal for USB_IN */ | 688 | /* Ouput Terminal for USB_IN */ |
689 | struct uac2_output_terminal_descriptor usb_in_ot_desc = { | 689 | static struct uac2_output_terminal_descriptor usb_in_ot_desc = { |
690 | .bLength = sizeof usb_in_ot_desc, | 690 | .bLength = sizeof usb_in_ot_desc, |
691 | .bDescriptorType = USB_DT_CS_INTERFACE, | 691 | .bDescriptorType = USB_DT_CS_INTERFACE, |
692 | 692 | ||
@@ -700,7 +700,7 @@ struct uac2_output_terminal_descriptor usb_in_ot_desc = { | |||
700 | }; | 700 | }; |
701 | 701 | ||
702 | /* Ouput Terminal for I/O-Out */ | 702 | /* Ouput Terminal for I/O-Out */ |
703 | struct uac2_output_terminal_descriptor io_out_ot_desc = { | 703 | static struct uac2_output_terminal_descriptor io_out_ot_desc = { |
704 | .bLength = sizeof io_out_ot_desc, | 704 | .bLength = sizeof io_out_ot_desc, |
705 | .bDescriptorType = USB_DT_CS_INTERFACE, | 705 | .bDescriptorType = USB_DT_CS_INTERFACE, |
706 | 706 | ||
@@ -713,7 +713,7 @@ struct uac2_output_terminal_descriptor io_out_ot_desc = { | |||
713 | .bmControls = (CONTROL_RDWR << COPY_CTRL), | 713 | .bmControls = (CONTROL_RDWR << COPY_CTRL), |
714 | }; | 714 | }; |
715 | 715 | ||
716 | struct uac2_ac_header_descriptor ac_hdr_desc = { | 716 | static struct uac2_ac_header_descriptor ac_hdr_desc = { |
717 | .bLength = sizeof ac_hdr_desc, | 717 | .bLength = sizeof ac_hdr_desc, |
718 | .bDescriptorType = USB_DT_CS_INTERFACE, | 718 | .bDescriptorType = USB_DT_CS_INTERFACE, |
719 | 719 | ||
@@ -751,7 +751,7 @@ static struct usb_interface_descriptor std_as_out_if1_desc = { | |||
751 | }; | 751 | }; |
752 | 752 | ||
753 | /* Audio Stream OUT Intface Desc */ | 753 | /* Audio Stream OUT Intface Desc */ |
754 | struct uac2_as_header_descriptor as_out_hdr_desc = { | 754 | static struct uac2_as_header_descriptor as_out_hdr_desc = { |
755 | .bLength = sizeof as_out_hdr_desc, | 755 | .bLength = sizeof as_out_hdr_desc, |
756 | .bDescriptorType = USB_DT_CS_INTERFACE, | 756 | .bDescriptorType = USB_DT_CS_INTERFACE, |
757 | 757 | ||
@@ -764,7 +764,7 @@ struct uac2_as_header_descriptor as_out_hdr_desc = { | |||
764 | }; | 764 | }; |
765 | 765 | ||
766 | /* Audio USB_OUT Format */ | 766 | /* Audio USB_OUT Format */ |
767 | struct uac2_format_type_i_descriptor as_out_fmt1_desc = { | 767 | static struct uac2_format_type_i_descriptor as_out_fmt1_desc = { |
768 | .bLength = sizeof as_out_fmt1_desc, | 768 | .bLength = sizeof as_out_fmt1_desc, |
769 | .bDescriptorType = USB_DT_CS_INTERFACE, | 769 | .bDescriptorType = USB_DT_CS_INTERFACE, |
770 | .bDescriptorSubtype = UAC_FORMAT_TYPE, | 770 | .bDescriptorSubtype = UAC_FORMAT_TYPE, |
@@ -772,7 +772,7 @@ struct uac2_format_type_i_descriptor as_out_fmt1_desc = { | |||
772 | }; | 772 | }; |
773 | 773 | ||
774 | /* STD AS ISO OUT Endpoint */ | 774 | /* STD AS ISO OUT Endpoint */ |
775 | struct usb_endpoint_descriptor fs_epout_desc = { | 775 | static struct usb_endpoint_descriptor fs_epout_desc = { |
776 | .bLength = USB_DT_ENDPOINT_SIZE, | 776 | .bLength = USB_DT_ENDPOINT_SIZE, |
777 | .bDescriptorType = USB_DT_ENDPOINT, | 777 | .bDescriptorType = USB_DT_ENDPOINT, |
778 | 778 | ||
@@ -782,7 +782,7 @@ struct usb_endpoint_descriptor fs_epout_desc = { | |||
782 | .bInterval = 1, | 782 | .bInterval = 1, |
783 | }; | 783 | }; |
784 | 784 | ||
785 | struct usb_endpoint_descriptor hs_epout_desc = { | 785 | static struct usb_endpoint_descriptor hs_epout_desc = { |
786 | .bLength = USB_DT_ENDPOINT_SIZE, | 786 | .bLength = USB_DT_ENDPOINT_SIZE, |
787 | .bDescriptorType = USB_DT_ENDPOINT, | 787 | .bDescriptorType = USB_DT_ENDPOINT, |
788 | 788 | ||
@@ -828,7 +828,7 @@ static struct usb_interface_descriptor std_as_in_if1_desc = { | |||
828 | }; | 828 | }; |
829 | 829 | ||
830 | /* Audio Stream IN Intface Desc */ | 830 | /* Audio Stream IN Intface Desc */ |
831 | struct uac2_as_header_descriptor as_in_hdr_desc = { | 831 | static struct uac2_as_header_descriptor as_in_hdr_desc = { |
832 | .bLength = sizeof as_in_hdr_desc, | 832 | .bLength = sizeof as_in_hdr_desc, |
833 | .bDescriptorType = USB_DT_CS_INTERFACE, | 833 | .bDescriptorType = USB_DT_CS_INTERFACE, |
834 | 834 | ||
@@ -841,7 +841,7 @@ struct uac2_as_header_descriptor as_in_hdr_desc = { | |||
841 | }; | 841 | }; |
842 | 842 | ||
843 | /* Audio USB_IN Format */ | 843 | /* Audio USB_IN Format */ |
844 | struct uac2_format_type_i_descriptor as_in_fmt1_desc = { | 844 | static struct uac2_format_type_i_descriptor as_in_fmt1_desc = { |
845 | .bLength = sizeof as_in_fmt1_desc, | 845 | .bLength = sizeof as_in_fmt1_desc, |
846 | .bDescriptorType = USB_DT_CS_INTERFACE, | 846 | .bDescriptorType = USB_DT_CS_INTERFACE, |
847 | .bDescriptorSubtype = UAC_FORMAT_TYPE, | 847 | .bDescriptorSubtype = UAC_FORMAT_TYPE, |
@@ -849,7 +849,7 @@ struct uac2_format_type_i_descriptor as_in_fmt1_desc = { | |||
849 | }; | 849 | }; |
850 | 850 | ||
851 | /* STD AS ISO IN Endpoint */ | 851 | /* STD AS ISO IN Endpoint */ |
852 | struct usb_endpoint_descriptor fs_epin_desc = { | 852 | static struct usb_endpoint_descriptor fs_epin_desc = { |
853 | .bLength = USB_DT_ENDPOINT_SIZE, | 853 | .bLength = USB_DT_ENDPOINT_SIZE, |
854 | .bDescriptorType = USB_DT_ENDPOINT, | 854 | .bDescriptorType = USB_DT_ENDPOINT, |
855 | 855 | ||
@@ -859,7 +859,7 @@ struct usb_endpoint_descriptor fs_epin_desc = { | |||
859 | .bInterval = 1, | 859 | .bInterval = 1, |
860 | }; | 860 | }; |
861 | 861 | ||
862 | struct usb_endpoint_descriptor hs_epin_desc = { | 862 | static struct usb_endpoint_descriptor hs_epin_desc = { |
863 | .bLength = USB_DT_ENDPOINT_SIZE, | 863 | .bLength = USB_DT_ENDPOINT_SIZE, |
864 | .bDescriptorType = USB_DT_ENDPOINT, | 864 | .bDescriptorType = USB_DT_ENDPOINT, |
865 | 865 | ||
@@ -1563,7 +1563,7 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) | |||
1563 | agdev->out_ep->driver_data = NULL; | 1563 | agdev->out_ep->driver_data = NULL; |
1564 | } | 1564 | } |
1565 | 1565 | ||
1566 | struct usb_function *afunc_alloc(struct usb_function_instance *fi) | 1566 | static struct usb_function *afunc_alloc(struct usb_function_instance *fi) |
1567 | { | 1567 | { |
1568 | struct audio_dev *agdev; | 1568 | struct audio_dev *agdev; |
1569 | struct f_uac2_opts *opts; | 1569 | struct f_uac2_opts *opts; |
diff --git a/drivers/usb/gadget/function/g_zero.h b/drivers/usb/gadget/function/g_zero.h index 2ce28b9d97cc..15f180904f8a 100644 --- a/drivers/usb/gadget/function/g_zero.h +++ b/drivers/usb/gadget/function/g_zero.h | |||
@@ -10,8 +10,6 @@ | |||
10 | #define GZERO_QLEN 32 | 10 | #define GZERO_QLEN 32 |
11 | #define GZERO_ISOC_INTERVAL 4 | 11 | #define GZERO_ISOC_INTERVAL 4 |
12 | #define GZERO_ISOC_MAXPACKET 1024 | 12 | #define GZERO_ISOC_MAXPACKET 1024 |
13 | #define GZERO_INT_INTERVAL 1 /* Default interrupt interval = 1 ms */ | ||
14 | #define GZERO_INT_MAXPACKET 1024 | ||
15 | 13 | ||
16 | struct usb_zero_options { | 14 | struct usb_zero_options { |
17 | unsigned pattern; | 15 | unsigned pattern; |
@@ -19,10 +17,6 @@ struct usb_zero_options { | |||
19 | unsigned isoc_maxpacket; | 17 | unsigned isoc_maxpacket; |
20 | unsigned isoc_mult; | 18 | unsigned isoc_mult; |
21 | unsigned isoc_maxburst; | 19 | unsigned isoc_maxburst; |
22 | unsigned int_interval; /* In ms */ | ||
23 | unsigned int_maxpacket; | ||
24 | unsigned int_mult; | ||
25 | unsigned int_maxburst; | ||
26 | unsigned bulk_buflen; | 20 | unsigned bulk_buflen; |
27 | unsigned qlen; | 21 | unsigned qlen; |
28 | }; | 22 | }; |
@@ -34,10 +28,6 @@ struct f_ss_opts { | |||
34 | unsigned isoc_maxpacket; | 28 | unsigned isoc_maxpacket; |
35 | unsigned isoc_mult; | 29 | unsigned isoc_mult; |
36 | unsigned isoc_maxburst; | 30 | unsigned isoc_maxburst; |
37 | unsigned int_interval; /* In ms */ | ||
38 | unsigned int_maxpacket; | ||
39 | unsigned int_mult; | ||
40 | unsigned int_maxburst; | ||
41 | unsigned bulk_buflen; | 31 | unsigned bulk_buflen; |
42 | 32 | ||
43 | /* | 33 | /* |
@@ -72,7 +62,6 @@ int lb_modinit(void); | |||
72 | void free_ep_req(struct usb_ep *ep, struct usb_request *req); | 62 | void free_ep_req(struct usb_ep *ep, struct usb_request *req); |
73 | void disable_endpoints(struct usb_composite_dev *cdev, | 63 | void disable_endpoints(struct usb_composite_dev *cdev, |
74 | struct usb_ep *in, struct usb_ep *out, | 64 | struct usb_ep *in, struct usb_ep *out, |
75 | struct usb_ep *iso_in, struct usb_ep *iso_out, | 65 | struct usb_ep *iso_in, struct usb_ep *iso_out); |
76 | struct usb_ep *int_in, struct usb_ep *int_out); | ||
77 | 66 | ||
78 | #endif /* __G_ZERO_H */ | 67 | #endif /* __G_ZERO_H */ |
diff --git a/drivers/usb/gadget/function/u_printer.h b/drivers/usb/gadget/function/u_printer.h new file mode 100644 index 000000000000..0e2c49d4274e --- /dev/null +++ b/drivers/usb/gadget/function/u_printer.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * u_printer.h | ||
3 | * | ||
4 | * Utility definitions for the printer function | ||
5 | * | ||
6 | * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_PRINTER_H | ||
17 | #define U_PRINTER_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | #define PNP_STRING_LEN 1024 | ||
22 | |||
23 | struct f_printer_opts { | ||
24 | struct usb_function_instance func_inst; | ||
25 | int minor; | ||
26 | char pnp_string[PNP_STRING_LEN]; | ||
27 | unsigned q_len; | ||
28 | |||
29 | /* | ||
30 | * Protect the data from concurrent access by read/write | ||
31 | * and create symlink/remove symlink | ||
32 | */ | ||
33 | struct mutex lock; | ||
34 | int refcnt; | ||
35 | }; | ||
36 | |||
37 | #endif /* U_PRINTER_H */ | ||
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 491082aaf103..89179ab20c10 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c | |||
@@ -912,7 +912,7 @@ static int gs_put_char(struct tty_struct *tty, unsigned char ch) | |||
912 | unsigned long flags; | 912 | unsigned long flags; |
913 | int status; | 913 | int status; |
914 | 914 | ||
915 | pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %pf\n", | 915 | pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %ps\n", |
916 | port->port_num, tty, ch, __builtin_return_address(0)); | 916 | port->port_num, tty, ch, __builtin_return_address(0)); |
917 | 917 | ||
918 | spin_lock_irqsave(&port->port_lock, flags); | 918 | spin_lock_irqsave(&port->port_lock, flags); |
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index cbd9bf020fb3..f4ccbd56f4d2 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "uvc.h" | 26 | #include "uvc.h" |
27 | #include "uvc_queue.h" | 27 | #include "uvc_queue.h" |
28 | #include "uvc_video.h" | 28 | #include "uvc_video.h" |
29 | #include "uvc_v4l2.h" | ||
29 | 30 | ||
30 | /* -------------------------------------------------------------------------- | 31 | /* -------------------------------------------------------------------------- |
31 | * Requests handling | 32 | * Requests handling |
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 8927358caf24..3d0d5d94a62f 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include "uvc.h" | 22 | #include "uvc.h" |
23 | #include "uvc_queue.h" | 23 | #include "uvc_queue.h" |
24 | #include "uvc_video.h" | ||
24 | 25 | ||
25 | /* -------------------------------------------------------------------------- | 26 | /* -------------------------------------------------------------------------- |
26 | * Video codecs | 27 | * Video codecs |