Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: hid: add configfs support

Make the hid function available for gadgets composed with configfs.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>

authored by

Andrzej Pietrasiewicz and committed by
Felipe Balbi
21a9476a 5ca8d3ec

+178 -1
+11
Documentation/ABI/testing/configfs-usb-gadget-hid
··· 1 + What: /config/usb-gadget/gadget/functions/hid.name 2 + Date: Nov 2014 3 + KernelVersion: 3.19 4 + Description: 5 + The attributes: 6 + 7 + protocol - HID protocol to use 8 + report_desc - blob corresponding to HID report descriptors 9 + except the data passed through /dev/hidg<N> 10 + report_length - HID report length 11 + subclass - HID device subclass to use
+7
Documentation/usb/gadget_hid.txt
··· 74 74 You can add as many HID functions as you want, only limited by 75 75 the amount of interrupt endpoints your gadget driver supports. 76 76 77 + Configuration with configfs 78 + 79 + Instead of adding fake platform devices and drivers in order to pass 80 + some data to the kernel, if HID is a part of a gadget composed with 81 + configfs the hidg_func_descriptor.report_desc is passed to the kernel 82 + by writing the appropriate stream of bytes to a configfs attribute. 83 + 77 84 Send and receive HID reports 78 85 79 86 HID reports can be sent/received using read/write on the
+10
drivers/usb/gadget/Kconfig
··· 413 413 connections can then be made on the gadget system, using 414 414 ALSA's aconnect utility etc. 415 415 416 + config USB_CONFIGFS_F_HID 417 + boolean "HID function" 418 + depends on USB_CONFIGFS 419 + select USB_F_HID 420 + help 421 + The HID function driver provides generic emulation of USB 422 + Human Interface Devices (HID). 423 + 424 + For more information, see Documentation/usb/gadget_hid.txt. 425 + 416 426 source "drivers/usb/gadget/legacy/Kconfig" 417 427 418 428 endchoice
+143 -1
drivers/usb/gadget/function/f_hid.c
··· 690 690 return ret; 691 691 } 692 692 693 + static inline struct f_hid_opts *to_f_hid_opts(struct config_item *item) 694 + { 695 + return container_of(to_config_group(item), struct f_hid_opts, 696 + func_inst.group); 697 + } 698 + 699 + CONFIGFS_ATTR_STRUCT(f_hid_opts); 700 + CONFIGFS_ATTR_OPS(f_hid_opts); 701 + 702 + static void hid_attr_release(struct config_item *item) 703 + { 704 + struct f_hid_opts *opts = to_f_hid_opts(item); 705 + 706 + usb_put_function_instance(&opts->func_inst); 707 + } 708 + 709 + static struct configfs_item_operations hidg_item_ops = { 710 + .release = hid_attr_release, 711 + .show_attribute = f_hid_opts_attr_show, 712 + .store_attribute = f_hid_opts_attr_store, 713 + }; 714 + 715 + #define F_HID_OPT(name, prec, limit) \ 716 + static ssize_t f_hid_opts_##name##_show(struct f_hid_opts *opts, char *page)\ 717 + { \ 718 + int result; \ 719 + \ 720 + mutex_lock(&opts->lock); \ 721 + result = sprintf(page, "%d\n", opts->name); \ 722 + mutex_unlock(&opts->lock); \ 723 + \ 724 + return result; \ 725 + } \ 726 + \ 727 + static ssize_t f_hid_opts_##name##_store(struct f_hid_opts *opts, \ 728 + const char *page, size_t len) \ 729 + { \ 730 + int ret; \ 731 + u##prec num; \ 732 + \ 733 + mutex_lock(&opts->lock); \ 734 + if (opts->refcnt) { \ 735 + ret = -EBUSY; \ 736 + goto end; \ 737 + } \ 738 + \ 739 + ret = kstrtou##prec(page, 0, &num); \ 740 + if (ret) \ 741 + goto end; \ 742 + \ 743 + if (num > limit) { \ 744 + ret = -EINVAL; \ 745 + goto end; \ 746 + } \ 747 + opts->name = num; \ 748 + ret = len; \ 749 + \ 750 + end: \ 751 + mutex_unlock(&opts->lock); \ 752 + return ret; \ 753 + } \ 754 + \ 755 + static struct f_hid_opts_attribute f_hid_opts_##name = \ 756 + __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_hid_opts_##name##_show,\ 757 + f_hid_opts_##name##_store) 758 + 759 + F_HID_OPT(subclass, 8, 255); 760 + F_HID_OPT(protocol, 8, 255); 761 + F_HID_OPT(report_length, 16, 65536); 762 + 763 + static ssize_t f_hid_opts_report_desc_show(struct f_hid_opts *opts, char *page) 764 + { 765 + int result; 766 + 767 + mutex_lock(&opts->lock); 768 + result = opts->report_desc_length; 769 + memcpy(page, opts->report_desc, opts->report_desc_length); 770 + mutex_unlock(&opts->lock); 771 + 772 + return result; 773 + } 774 + 775 + static ssize_t f_hid_opts_report_desc_store(struct f_hid_opts *opts, 776 + const char *page, size_t len) 777 + { 778 + int ret = -EBUSY; 779 + char *d; 780 + 781 + mutex_lock(&opts->lock); 782 + 783 + if (opts->refcnt) 784 + goto end; 785 + if (len > PAGE_SIZE) { 786 + ret = -ENOSPC; 787 + goto end; 788 + } 789 + d = kmemdup(page, len, GFP_KERNEL); 790 + if (!d) { 791 + ret = -ENOMEM; 792 + goto end; 793 + } 794 + kfree(opts->report_desc); 795 + opts->report_desc = d; 796 + opts->report_desc_length = len; 797 + opts->report_desc_alloc = true; 798 + ret = len; 799 + end: 800 + mutex_unlock(&opts->lock); 801 + return ret; 802 + } 803 + 804 + static struct f_hid_opts_attribute f_hid_opts_report_desc = 805 + __CONFIGFS_ATTR(report_desc, S_IRUGO | S_IWUSR, 806 + f_hid_opts_report_desc_show, 807 + f_hid_opts_report_desc_store); 808 + 809 + static struct configfs_attribute *hid_attrs[] = { 810 + &f_hid_opts_subclass.attr, 811 + &f_hid_opts_protocol.attr, 812 + &f_hid_opts_report_length.attr, 813 + &f_hid_opts_report_desc.attr, 814 + NULL, 815 + }; 816 + 817 + static struct config_item_type hid_func_type = { 818 + .ct_item_ops = &hidg_item_ops, 819 + .ct_attrs = hid_attrs, 820 + .ct_owner = THIS_MODULE, 821 + }; 822 + 693 823 static inline void hidg_put_minor(int minor) 694 824 { 695 825 ida_simple_remove(&hidg_ida, minor); ··· 854 724 opts = kzalloc(sizeof(*opts), GFP_KERNEL); 855 725 if (!opts) 856 726 return ERR_PTR(-ENOMEM); 857 - 727 + mutex_init(&opts->lock); 858 728 opts->func_inst.free_func_inst = hidg_free_inst; 859 729 ret = &opts->func_inst; 860 730 ··· 876 746 if (idr_is_empty(&hidg_ida.idr)) 877 747 ghid_cleanup(); 878 748 } 749 + config_group_init_type_name(&opts->func_inst.group, "", &hid_func_type); 879 750 880 751 unlock: 881 752 mutex_unlock(&hidg_ida_lock); ··· 886 755 static void hidg_free(struct usb_function *f) 887 756 { 888 757 struct f_hidg *hidg; 758 + struct f_hid_opts *opts; 889 759 890 760 hidg = func_to_hidg(f); 761 + opts = container_of(f->fi, struct f_hid_opts, func_inst); 891 762 kfree(hidg->report_desc); 892 763 kfree(hidg); 764 + mutex_lock(&opts->lock); 765 + --opts->refcnt; 766 + mutex_unlock(&opts->lock); 893 767 } 894 768 895 769 static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) ··· 925 789 926 790 opts = container_of(fi, struct f_hid_opts, func_inst); 927 791 792 + mutex_lock(&opts->lock); 793 + ++opts->refcnt; 794 + 928 795 hidg->minor = opts->minor; 929 796 hidg->bInterfaceSubClass = opts->subclass; 930 797 hidg->bInterfaceProtocol = opts->protocol; ··· 939 800 GFP_KERNEL); 940 801 if (!hidg->report_desc) { 941 802 kfree(hidg); 803 + mutex_unlock(&opts->lock); 942 804 return ERR_PTR(-ENOMEM); 943 805 } 944 806 } 807 + 808 + mutex_unlock(&opts->lock); 945 809 946 810 hidg->func.name = "hid"; 947 811 hidg->func.bind = hidg_bind;
+7
drivers/usb/gadget/function/u_hid.h
··· 27 27 unsigned short report_desc_length; 28 28 unsigned char *report_desc; 29 29 bool report_desc_alloc; 30 + 31 + /* 32 + * Protect the data form concurrent access by read/write 33 + * and create symlink/remove symlink. 34 + */ 35 + struct mutex lock; 36 + int refcnt; 30 37 }; 31 38 32 39 int ghid_setup(struct usb_gadget *g, int count);