| @@ -7,6 +7,7 @@ · 6 unmodified lines |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 9 | #include <linux/compiler.h> |
| 10 | +#include <linux/ctype.h> |
| 10 | 11 | #include <linux/debugfs.h> |
| 11 | 12 | #include <linux/delay.h> |
| 12 | 13 | #include <linux/kref.h> |
| @@ -123,8 +124,6 @@ static void raw_event_queue_destroy(struct raw_event_queue *queue) · 110 unmodified lines |
| 123 | 124 | |
| 124 | 125 | struct raw_dev; |
| 125 | 126 | |
| 126 | | −#define USB_RAW_MAX_ENDPOINTS 32 |
| 127 | | − |
| 128 | 127 | enum ep_state { |
| 129 | 128 | STATE_EP_DISABLED, |
| 130 | 129 | STATE_EP_ENABLED, |
| @@ -134,6 +133,7 @@ struct raw_ep { · 3 unmodified lines |
| 134 | 133 | struct raw_dev *dev; |
| 135 | 134 | enum ep_state state; |
| 136 | 135 | struct usb_ep *ep; |
| 136 | + u8 addr; |
| 137 | 137 | struct usb_request *req; |
| 138 | 138 | bool urb_queued; |
| 139 | 139 | bool disabling; |
| @@ -168,7 +168,8 @@ struct raw_dev { · 28 unmodified lines |
| 168 | 168 | bool ep0_out_pending; |
| 169 | 169 | bool ep0_urb_queued; |
| 170 | 170 | ssize_t ep0_status; |
| 171 | | − struct raw_ep eps[USB_RAW_MAX_ENDPOINTS]; |
| 171 | + struct raw_ep eps[USB_RAW_EPS_NUM_MAX]; |
| 172 | + int eps_num; |
| 172 | 173 | |
| 173 | 174 | struct completion ep0_done; |
| 174 | 175 | struct raw_event_queue queue; |
| @@ -202,7 +203,7 @@ static void dev_free(struct kref *kref) · 27 unmodified lines |
| 202 | 203 | usb_ep_free_request(dev->gadget->ep0, dev->req); |
| 203 | 204 | } |
| 204 | 205 | raw_event_queue_destroy(&dev->queue); |
| 205 | | − for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) { |
| 206 | + for (i = 0; i < dev->eps_num; i++) { |
| 206 | 207 | if (dev->eps[i].state != STATE_EP_ENABLED) |
| 207 | 208 | continue; |
| 208 | 209 | usb_ep_disable(dev->eps[i].ep); |
| @@ -249,12 +250,26 @@ static void gadget_ep0_complete(struct usb_ep *ep, struct usb_request *req) · 40 unmodified lines |
| 249 | 250 | complete(&dev->ep0_done); |
| 250 | 251 | } |
| 251 | 252 | |
| 253 | +static u8 get_ep_addr(const char *name) |
| 254 | +{ |
| 255 | + /* If the endpoint has fixed function (named as e.g. "ep12out-bulk"), |
| 256 | + * parse the endpoint address from its name. We deliberately use |
| 257 | + * deprecated simple_strtoul() function here, as the number isn't |
| 258 | + * followed by '\0' nor '\n'. |
| 259 | + */ |
| 260 | + if (isdigit(name[2])) |
| 261 | + return simple_strtoul(&name[2], NULL, 10); |
| 262 | + /* Otherwise the endpoint is configurable (named as e.g. "ep-a"). */ |
| 263 | + return USB_RAW_EP_ADDR_ANY; |
| 264 | +} |
| 265 | + |
| 252 | 266 | static int gadget_bind(struct usb_gadget *gadget, |
| 253 | 267 | struct usb_gadget_driver *driver) |
| 254 | 268 | { |
| 255 | | − int ret = 0; |
| 269 | + int ret = 0, i = 0; |
| 256 | 270 | struct raw_dev *dev = container_of(driver, struct raw_dev, driver); |
| 257 | 271 | struct usb_request *req; |
| 272 | + struct usb_ep *ep; |
| 258 | 273 | unsigned long flags; |
| 259 | 274 | |
| 260 | 275 | if (strcmp(gadget->name, dev->udc_name) != 0) |
| @@ -273,6 +288,13 @@ static int gadget_bind(struct usb_gadget *gadget, · 12 unmodified lines |
| 273 | 288 | dev->req->context = dev; |
| 274 | 289 | dev->req->complete = gadget_ep0_complete; |
| 275 | 290 | dev->gadget = gadget; |
| 291 | + gadget_for_each_ep(ep, dev->gadget) { |
| 292 | + dev->eps[i].ep = ep; |
| 293 | + dev->eps[i].addr = get_ep_addr(ep->name); |
| 294 | + dev->eps[i].state = STATE_EP_DISABLED; |
| 295 | + i++; |
| 296 | + } |
| 297 | + dev->eps_num = i; |
| 276 | 298 | spin_unlock_irqrestore(&dev->lock, flags); |
| 277 | 299 | |
| 278 | 300 | /* Matches kref_put() in gadget_unbind(). */ |
| @@ -555,7 +577,7 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr, · 276 unmodified lines |
| 555 | 577 | |
| 556 | 578 | if (copy_from_user(io, ptr, sizeof(*io))) |
| 557 | 579 | return ERR_PTR(-EFAULT); |
| 558 | | − if (io->ep >= USB_RAW_MAX_ENDPOINTS) |
| 580 | + if (io->ep >= USB_RAW_EPS_NUM_MAX) |
| 559 | 581 | return ERR_PTR(-EINVAL); |
| 560 | 582 | if (!usb_raw_io_flags_valid(io->flags)) |
| 561 | 583 | return ERR_PTR(-EINVAL); |
| @@ -682,40 +704,12 @@ free: · 120 unmodified lines |
| 682 | 704 | return ret; |
| 683 | 705 | } |
| 684 | 706 | |
| 685 | | −static bool check_ep_caps(struct usb_ep *ep, |
| 686 | | − struct usb_endpoint_descriptor *desc) |
| 687 | | −{ |
| 688 | | − switch (usb_endpoint_type(desc)) { |
| 689 | | − case USB_ENDPOINT_XFER_ISOC: |
| 690 | | − if (!ep->caps.type_iso) |
| 691 | | − return false; |
| 692 | | − break; |
| 693 | | − case USB_ENDPOINT_XFER_BULK: |
| 694 | | − if (!ep->caps.type_bulk) |
| 695 | | − return false; |
| 696 | | − break; |
| 697 | | − case USB_ENDPOINT_XFER_INT: |
| 698 | | − if (!ep->caps.type_int) |
| 699 | | − return false; |
| 700 | | − break; |
| 701 | | − default: |
| 702 | | − return false; |
| 703 | | − } |
| 704 | | − |
| 705 | | − if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) |
| 706 | | − return false; |
| 707 | | − if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) |
| 708 | | − return false; |
| 709 | | − |
| 710 | | − return true; |
| 711 | | −} |
| 712 | | − |
| 713 | 707 | static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) |
| 714 | 708 | { |
| 715 | 709 | int ret = 0, i; |
| 716 | 710 | unsigned long flags; |
| 717 | 711 | struct usb_endpoint_descriptor *desc; |
| 718 | | − struct usb_ep *ep = NULL; |
| 712 | + struct raw_ep *ep; |
| 719 | 713 | |
| 720 | 714 | desc = memdup_user((void __user *)value, sizeof(*desc)); |
| 721 | 715 | if (IS_ERR(desc)) |
| @@ -743,41 +737,32 @@ static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) · 21 unmodified lines |
| 743 | 737 | goto out_free; |
| 744 | 738 | } |
| 745 | 739 | |
| 746 | | − for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) { |
| 747 | | − if (dev->eps[i].state == STATE_EP_ENABLED) |
| 740 | + for (i = 0; i < dev->eps_num; i++) { |
| 741 | + ep = &dev->eps[i]; |
| 742 | + if (ep->state != STATE_EP_DISABLED) |
| 748 | 743 | continue; |
| 749 | | − break; |
| 750 | | − } |
| 751 | | − if (i == USB_RAW_MAX_ENDPOINTS) { |
| 752 | | − dev_dbg(&dev->gadget->dev, |
| 753 | | − "fail, no device endpoints available\n"); |
| 754 | | − ret = -EBUSY; |
| 755 | | − goto out_free; |
| 756 | | − } |
| 757 | | − |
| 758 | | − gadget_for_each_ep(ep, dev->gadget) { |
| 759 | | − if (ep->enabled) |
| 744 | + if (ep->addr != usb_endpoint_num(desc) && |
| 745 | + ep->addr != USB_RAW_EP_ADDR_ANY) |
| 760 | 746 | continue; |
| 761 | | − if (!check_ep_caps(ep, desc)) |
| 747 | + if (!usb_gadget_ep_match_desc(dev->gadget, ep->ep, desc, NULL)) |
| 762 | 748 | continue; |
| 763 | | − ep->desc = desc; |
| 764 | | − ret = usb_ep_enable(ep); |
| 749 | + ep->ep->desc = desc; |
| 750 | + ret = usb_ep_enable(ep->ep); |
| 765 | 751 | if (ret < 0) { |
| 766 | 752 | dev_err(&dev->gadget->dev, |
| 767 | 753 | "fail, usb_ep_enable returned %d\n", ret); |
| 768 | 754 | goto out_free; |
| 769 | 755 | } |
| 770 | | − dev->eps[i].req = usb_ep_alloc_request(ep, GFP_ATOMIC); |
| 771 | | − if (!dev->eps[i].req) { |
| 756 | + ep->req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC); |
| 757 | + if (!ep->req) { |
| 772 | 758 | dev_err(&dev->gadget->dev, |
| 773 | 759 | "fail, usb_ep_alloc_request failed\n"); |
| 774 | | − usb_ep_disable(ep); |
| 760 | + usb_ep_disable(ep->ep); |
| 775 | 761 | ret = -ENOMEM; |
| 776 | 762 | goto out_free; |
| 777 | 763 | } |
| 778 | | − dev->eps[i].ep = ep; |
| 779 | | − dev->eps[i].state = STATE_EP_ENABLED; |
| 780 | | − ep->driver_data = &dev->eps[i]; |
| 764 | + ep->state = STATE_EP_ENABLED; |
| 765 | + ep->ep->driver_data = ep; |
| 781 | 766 | ret = i; |
| 782 | 767 | goto out_unlock; |
| 783 | 768 | } |
| @@ -796,10 +781,6 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) · 12 unmodified lines |
| 796 | 781 | { |
| 797 | 782 | int ret = 0, i = value; |
| 798 | 783 | unsigned long flags; |
| 799 | | − const void *desc; |
| 800 | | − |
| 801 | | − if (i < 0 || i >= USB_RAW_MAX_ENDPOINTS) |
| 802 | | − return -EINVAL; |
| 803 | 784 | |
| 804 | 785 | spin_lock_irqsave(&dev->lock, flags); |
| 805 | 786 | if (dev->state != STATE_DEV_RUNNING) { |
| @@ -812,6 +793,11 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) · 6 unmodified lines |
| 812 | 793 | ret = -EBUSY; |
| 813 | 794 | goto out_unlock; |
| 814 | 795 | } |
| 796 | + if (i < 0 || i >= dev->eps_num) { |
| 797 | + dev_dbg(dev->dev, "fail, invalid endpoint\n"); |
| 798 | + ret = -EBUSY; |
| 799 | + goto out_unlock; |
| 800 | + } |
| 815 | 801 | if (dev->eps[i].state != STATE_EP_ENABLED) { |
| 816 | 802 | dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); |
| 817 | 803 | ret = -EINVAL; |
| @@ -836,10 +822,9 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) · 18 unmodified lines |
| 836 | 822 | |
| 837 | 823 | spin_lock_irqsave(&dev->lock, flags); |
| 838 | 824 | usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); |
| 839 | | − desc = dev->eps[i].ep->desc; |
| 825 | + kfree(dev->eps[i].ep->desc); |
| 840 | 826 | dev->eps[i].ep = NULL; |
| 841 | 827 | dev->eps[i].state = STATE_EP_DISABLED; |
| 842 | | − kfree(desc); |
| 843 | 828 | dev->eps[i].disabling = false; |
| 844 | 829 | |
| 845 | 830 | out_unlock: |
| @@ -868,7 +853,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io, · 22 unmodified lines |
| 868 | 853 | { |
| 869 | 854 | int ret = 0; |
| 870 | 855 | unsigned long flags; |
| 871 | | − struct raw_ep *ep = &dev->eps[io->ep]; |
| 856 | + struct raw_ep *ep; |
| 872 | 857 | DECLARE_COMPLETION_ONSTACK(done); |
| 873 | 858 | |
| 874 | 859 | spin_lock_irqsave(&dev->lock, flags); |
| @@ -882,6 +867,12 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io, · 7 unmodified lines |
| 882 | 867 | ret = -EBUSY; |
| 883 | 868 | goto out_unlock; |
| 884 | 869 | } |
| 870 | + if (io->ep >= dev->eps_num) { |
| 871 | + dev_dbg(&dev->gadget->dev, "fail, invalid endpoint\n"); |
| 872 | + ret = -EINVAL; |
| 873 | + goto out_unlock; |
| 874 | + } |
| 875 | + ep = &dev->eps[io->ep]; |
| 885 | 876 | if (ep->state != STATE_EP_ENABLED) { |
| 886 | 877 | dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); |
| 887 | 878 | ret = -EBUSY; |
| @@ -1027,6 +1018,71 @@ out_unlock: · 139 unmodified lines |
| 1027 | 1018 | return ret; |
| 1028 | 1019 | } |
| 1029 | 1020 | |
| 1021 | +static void fill_ep_caps(struct usb_ep_caps *caps, |
| 1022 | + struct usb_raw_ep_caps *raw_caps) |
| 1023 | +{ |
| 1024 | + raw_caps->type_control = caps->type_control; |
| 1025 | + raw_caps->type_iso = caps->type_iso; |
| 1026 | + raw_caps->type_bulk = caps->type_bulk; |
| 1027 | + raw_caps->type_int = caps->type_int; |
| 1028 | + raw_caps->dir_in = caps->dir_in; |
| 1029 | + raw_caps->dir_out = caps->dir_out; |
| 1030 | +} |
| 1031 | + |
| 1032 | +static void fill_ep_limits(struct usb_ep *ep, struct usb_raw_ep_limits *limits) |
| 1033 | +{ |
| 1034 | + limits->maxpacket_limit = ep->maxpacket_limit; |
| 1035 | + limits->max_streams = ep->max_streams; |
| 1036 | +} |
| 1037 | + |
| 1038 | +static int raw_ioctl_eps_info(struct raw_dev *dev, unsigned long value) |
| 1039 | +{ |
| 1040 | + int ret = 0, i; |
| 1041 | + unsigned long flags; |
| 1042 | + struct usb_raw_eps_info *info; |
| 1043 | + struct raw_ep *ep; |
| 1044 | + |
| 1045 | + info = kmalloc(sizeof(*info), GFP_KERNEL); |
| 1046 | + if (!info) { |
| 1047 | + ret = -ENOMEM; |
| 1048 | + goto out; |
| 1049 | + } |
| 1050 | + |
| 1051 | + spin_lock_irqsave(&dev->lock, flags); |
| 1052 | + if (dev->state != STATE_DEV_RUNNING) { |
| 1053 | + dev_dbg(dev->dev, "fail, device is not running\n"); |
| 1054 | + ret = -EINVAL; |
| 1055 | + spin_unlock_irqrestore(&dev->lock, flags); |
| 1056 | + goto out_free; |
| 1057 | + } |
| 1058 | + if (!dev->gadget) { |
| 1059 | + dev_dbg(dev->dev, "fail, gadget is not bound\n"); |
| 1060 | + ret = -EBUSY; |
| 1061 | + spin_unlock_irqrestore(&dev->lock, flags); |
| 1062 | + goto out_free; |
| 1063 | + } |
| 1064 | + |
| 1065 | + memset(info, 0, sizeof(*info)); |
| 1066 | + for (i = 0; i < dev->eps_num; i++) { |
| 1067 | + ep = &dev->eps[i]; |
| 1068 | + strscpy(&info->eps[i].name[0], ep->ep->name, |
| 1069 | + USB_RAW_EP_NAME_MAX); |
| 1070 | + info->eps[i].addr = ep->addr; |
| 1071 | + fill_ep_caps(&ep->ep->caps, &info->eps[i].caps); |
| 1072 | + fill_ep_limits(ep->ep, &info->eps[i].limits); |
| 1073 | + } |
| 1074 | + ret = dev->eps_num; |
| 1075 | + spin_unlock_irqrestore(&dev->lock, flags); |
| 1076 | + |
| 1077 | + if (copy_to_user((void __user *)value, info, sizeof(*info))) |
| 1078 | + ret = -EFAULT; |
| 1079 | + |
| 1080 | +out_free: |
| 1081 | + kfree(info); |
| 1082 | +out: |
| 1083 | + return ret; |
| 1084 | +} |
| 1085 | + |
| 1030 | 1086 | static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) |
| 1031 | 1087 | { |
| 1032 | 1088 | struct raw_dev *dev = fd->private_data; |
| @@ -1069,6 +1125,9 @@ static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) · 36 unmodified lines |
| 1069 | 1125 | case USB_RAW_IOCTL_VBUS_DRAW: |
| 1070 | 1126 | ret = raw_ioctl_vbus_draw(dev, value); |
| 1071 | 1127 | break; |
| 1128 | + case USB_RAW_IOCTL_EPS_INFO: |
| 1129 | + ret = raw_ioctl_eps_info(dev, value); |
| 1130 | + break; |
| 1072 | 1131 | default: |
| 1073 | 1132 | ret = -EINVAL; |
| 1074 | 1133 | } |