aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>2014-11-06 05:11:59 -0500
committerFelipe Balbi <balbi@ti.com>2014-11-06 17:18:18 -0500
commitcb382536052fcc7713988869b54a81137069e5a9 (patch)
treeb47eb0c49597f56c9ee6d29ff2122fb7a13f6d0f
parent00896f66f5032e5f53874a76e02cdad09f7ff90b (diff)
usb: gadget: f_hid: convert to new function interface with backward compatibility
Converting hid to the new function interface requires converting the USB hid's function code and its users. This patch converts the f_hid.c to the new function interface. The file can now be compiled into a separate usb_f_hid.ko module. The old function interface is provided by means of a preprocessor conditional directives. After all users are converted, the old interface can be removed. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/gadget/Kconfig3
-rw-r--r--drivers/usb/gadget/function/Makefile2
-rw-r--r--drivers/usb/gadget/function/f_hid.c218
-rw-r--r--drivers/usb/gadget/function/u_hid.h35
-rw-r--r--drivers/usb/gadget/legacy/hid.c1
5 files changed, 227 insertions, 32 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 501c2a38d071..ea2d7706db6c 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -193,6 +193,9 @@ config USB_F_UVC
193config USB_F_MIDI 193config USB_F_MIDI
194 tristate 194 tristate
195 195
196config USB_F_HID
197 tristate
198
196choice 199choice
197 tristate "USB Gadget Drivers" 200 tristate "USB Gadget Drivers"
198 default USB_ETH 201 default USB_ETH
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index 576eea5c0a8b..dd68091d92f0 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -40,3 +40,5 @@ usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o
40obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o 40obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o
41usb_f_midi-y := f_midi.o 41usb_f_midi-y := f_midi.o
42obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o 42obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o
43usb_f_hid-y := f_hid.o
44obj-$(CONFIG_USB_F_HID) += usb_f_hid.o
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index ad538811c48b..f5dcf9480ba5 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -12,6 +12,7 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/hid.h> 14#include <linux/hid.h>
15#include <linux/idr.h>
15#include <linux/cdev.h> 16#include <linux/cdev.h>
16#include <linux/mutex.h> 17#include <linux/mutex.h>
17#include <linux/poll.h> 18#include <linux/poll.h>
@@ -21,9 +22,16 @@
21#include <linux/usb/g_hid.h> 22#include <linux/usb/g_hid.h>
22 23
23#include "u_f.h" 24#include "u_f.h"
25#include "u_hid.h"
26
27#define HIDG_MINORS 4
24 28
25static int major, minors; 29static int major, minors;
26static struct class *hidg_class; 30static struct class *hidg_class;
31#ifndef USBF_HID_INCLUDED
32static DEFINE_IDA(hidg_ida);
33static DEFINE_MUTEX(hidg_ida_lock); /* protects access to hidg_ida */
34#endif
27 35
28/*-------------------------------------------------------------------------*/ 36/*-------------------------------------------------------------------------*/
29/* HID gadget struct */ 37/* HID gadget struct */
@@ -161,6 +169,26 @@ static struct usb_descriptor_header *hidg_fs_descriptors[] = {
161}; 169};
162 170
163/*-------------------------------------------------------------------------*/ 171/*-------------------------------------------------------------------------*/
172/* Strings */
173
174#define CT_FUNC_HID_IDX 0
175
176static struct usb_string ct_func_string_defs[] = {
177 [CT_FUNC_HID_IDX].s = "HID Interface",
178 {}, /* end of list */
179};
180
181static struct usb_gadget_strings ct_func_string_table = {
182 .language = 0x0409, /* en-US */
183 .strings = ct_func_string_defs,
184};
185
186static struct usb_gadget_strings *ct_func_strings[] = {
187 &ct_func_string_table,
188 NULL,
189};
190
191/*-------------------------------------------------------------------------*/
164/* Char Device */ 192/* Char Device */
165 193
166static ssize_t f_hidg_read(struct file *file, char __user *buffer, 194static ssize_t f_hidg_read(struct file *file, char __user *buffer,
@@ -552,7 +580,7 @@ const struct file_operations f_hidg_fops = {
552 .llseek = noop_llseek, 580 .llseek = noop_llseek,
553}; 581};
554 582
555static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) 583static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
556{ 584{
557 struct usb_ep *ep; 585 struct usb_ep *ep;
558 struct f_hidg *hidg = func_to_hidg(f); 586 struct f_hidg *hidg = func_to_hidg(f);
@@ -560,6 +588,15 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
560 int status; 588 int status;
561 dev_t dev; 589 dev_t dev;
562 590
591 /* maybe allocate device-global string IDs, and patch descriptors */
592 if (ct_func_string_defs[CT_FUNC_HID_IDX].id == 0) {
593 status = usb_string_id(c->cdev);
594 if (status < 0)
595 return status;
596 ct_func_string_defs[CT_FUNC_HID_IDX].id = status;
597 hidg_interface_desc.iInterface = status;
598 }
599
563 /* allocate instance-specific interface IDs, and patch descriptors */ 600 /* allocate instance-specific interface IDs, and patch descriptors */
564 status = usb_interface_id(c, f); 601 status = usb_interface_id(c, f);
565 if (status < 0) 602 if (status < 0)
@@ -647,6 +684,7 @@ fail:
647 return status; 684 return status;
648} 685}
649 686
687#ifdef USBF_HID_INCLUDED
650static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) 688static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
651{ 689{
652 struct f_hidg *hidg = func_to_hidg(f); 690 struct f_hidg *hidg = func_to_hidg(f);
@@ -667,28 +705,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
667} 705}
668 706
669/*-------------------------------------------------------------------------*/ 707/*-------------------------------------------------------------------------*/
670/* Strings */
671
672#define CT_FUNC_HID_IDX 0
673
674static struct usb_string ct_func_string_defs[] = {
675 [CT_FUNC_HID_IDX].s = "HID Interface",
676 {}, /* end of list */
677};
678
679static struct usb_gadget_strings ct_func_string_table = {
680 .language = 0x0409, /* en-US */
681 .strings = ct_func_string_defs,
682};
683
684static struct usb_gadget_strings *ct_func_strings[] = {
685 &ct_func_string_table,
686 NULL,
687};
688
689/*-------------------------------------------------------------------------*/
690/* usb_configuration */ 708/* usb_configuration */
691
692int __init hidg_bind_config(struct usb_configuration *c, 709int __init hidg_bind_config(struct usb_configuration *c,
693 struct hidg_func_descriptor *fdesc, int index) 710 struct hidg_func_descriptor *fdesc, int index)
694{ 711{
@@ -698,15 +715,6 @@ int __init hidg_bind_config(struct usb_configuration *c,
698 if (index >= minors) 715 if (index >= minors)
699 return -ENOENT; 716 return -ENOENT;
700 717
701 /* maybe allocate device-global string IDs, and patch descriptors */
702 if (ct_func_string_defs[CT_FUNC_HID_IDX].id == 0) {
703 status = usb_string_id(c->cdev);
704 if (status < 0)
705 return status;
706 ct_func_string_defs[CT_FUNC_HID_IDX].id = status;
707 hidg_interface_desc.iInterface = status;
708 }
709
710 /* allocate and initialize one new instance */ 718 /* allocate and initialize one new instance */
711 hidg = kzalloc(sizeof *hidg, GFP_KERNEL); 719 hidg = kzalloc(sizeof *hidg, GFP_KERNEL);
712 if (!hidg) 720 if (!hidg)
@@ -743,7 +751,153 @@ int __init hidg_bind_config(struct usb_configuration *c,
743 return status; 751 return status;
744} 752}
745 753
746int __init ghid_setup(struct usb_gadget *g, int count) 754#else
755
756static inline int hidg_get_minor(void)
757{
758 int ret;
759
760 ret = ida_simple_get(&hidg_ida, 0, 0, GFP_KERNEL);
761
762 return ret;
763}
764
765static inline void hidg_put_minor(int minor)
766{
767 ida_simple_remove(&hidg_ida, minor);
768}
769
770static void hidg_free_inst(struct usb_function_instance *f)
771{
772 struct f_hid_opts *opts;
773
774 opts = container_of(f, struct f_hid_opts, func_inst);
775
776 mutex_lock(&hidg_ida_lock);
777
778 hidg_put_minor(opts->minor);
779 if (idr_is_empty(&hidg_ida.idr))
780 ghid_cleanup();
781
782 mutex_unlock(&hidg_ida_lock);
783
784 if (opts->report_desc_alloc)
785 kfree(opts->report_desc);
786
787 kfree(opts);
788}
789
790static struct usb_function_instance *hidg_alloc_inst(void)
791{
792 struct f_hid_opts *opts;
793 struct usb_function_instance *ret;
794 int status = 0;
795
796 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
797 if (!opts)
798 return ERR_PTR(-ENOMEM);
799
800 opts->func_inst.free_func_inst = hidg_free_inst;
801 ret = &opts->func_inst;
802
803 mutex_lock(&hidg_ida_lock);
804
805 if (idr_is_empty(&hidg_ida.idr)) {
806 status = ghid_setup(NULL, HIDG_MINORS);
807 if (status) {
808 ret = ERR_PTR(status);
809 kfree(opts);
810 goto unlock;
811 }
812 }
813
814 opts->minor = hidg_get_minor();
815 if (opts->minor < 0) {
816 ret = ERR_PTR(opts->minor);
817 kfree(opts);
818 if (idr_is_empty(&hidg_ida.idr))
819 ghid_cleanup();
820 }
821
822unlock:
823 mutex_unlock(&hidg_ida_lock);
824 return ret;
825}
826
827static void hidg_free(struct usb_function *f)
828{
829 struct f_hidg *hidg;
830
831 hidg = func_to_hidg(f);
832 kfree(hidg->report_desc);
833 kfree(hidg);
834}
835
836static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
837{
838 struct f_hidg *hidg = func_to_hidg(f);
839
840 device_destroy(hidg_class, MKDEV(major, hidg->minor));
841 cdev_del(&hidg->cdev);
842
843 /* disable/free request and end point */
844 usb_ep_disable(hidg->in_ep);
845 usb_ep_dequeue(hidg->in_ep, hidg->req);
846 kfree(hidg->req->buf);
847 usb_ep_free_request(hidg->in_ep, hidg->req);
848
849 usb_free_all_descriptors(f);
850}
851
852struct usb_function *hidg_alloc(struct usb_function_instance *fi)
853{
854 struct f_hidg *hidg;
855 struct f_hid_opts *opts;
856
857 /* allocate and initialize one new instance */
858 hidg = kzalloc(sizeof(*hidg), GFP_KERNEL);
859 if (!hidg)
860 return ERR_PTR(-ENOMEM);
861
862 opts = container_of(fi, struct f_hid_opts, func_inst);
863
864 hidg->minor = opts->minor;
865 hidg->bInterfaceSubClass = opts->subclass;
866 hidg->bInterfaceProtocol = opts->protocol;
867 hidg->report_length = opts->report_length;
868 hidg->report_desc_length = opts->report_desc_length;
869 if (opts->report_desc) {
870 hidg->report_desc = kmemdup(opts->report_desc,
871 opts->report_desc_length,
872 GFP_KERNEL);
873 if (!hidg->report_desc) {
874 kfree(hidg);
875 return ERR_PTR(-ENOMEM);
876 }
877 }
878
879 hidg->func.name = "hid";
880 hidg->func.strings = ct_func_strings;
881 hidg->func.bind = hidg_bind;
882 hidg->func.unbind = hidg_unbind;
883 hidg->func.set_alt = hidg_set_alt;
884 hidg->func.disable = hidg_disable;
885 hidg->func.setup = hidg_setup;
886 hidg->func.free_func = hidg_free;
887
888 /* this could me made configurable at some point */
889 hidg->qlen = 4;
890
891 return &hidg->func;
892}
893
894DECLARE_USB_FUNCTION_INIT(hid, hidg_alloc_inst, hidg_alloc);
895MODULE_LICENSE("GPL");
896MODULE_AUTHOR("Fabien Chouteau");
897
898#endif
899
900int ghid_setup(struct usb_gadget *g, int count)
747{ 901{
748 int status; 902 int status;
749 dev_t dev; 903 dev_t dev;
diff --git a/drivers/usb/gadget/function/u_hid.h b/drivers/usb/gadget/function/u_hid.h
new file mode 100644
index 000000000000..3edfc9567ab7
--- /dev/null
+++ b/drivers/usb/gadget/function/u_hid.h
@@ -0,0 +1,35 @@
1/*
2 * u_hid.h
3 *
4 * Utility definitions for the hid function
5 *
6 * Copyright (c) 2014 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_HID_H
17#define U_HID_H
18
19#include <linux/usb/composite.h>
20
21struct f_hid_opts {
22 struct usb_function_instance func_inst;
23 int minor;
24 unsigned char subclass;
25 unsigned char protocol;
26 unsigned short report_length;
27 unsigned short report_desc_length;
28 unsigned char *report_desc;
29 bool report_desc_alloc;
30};
31
32int ghid_setup(struct usb_gadget *g, int count);
33void ghid_cleanup(void);
34
35#endif /* U_HID_H */
diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c
index fba80a25260b..26cb4ea2aaf7 100644
--- a/drivers/usb/gadget/legacy/hid.c
+++ b/drivers/usb/gadget/legacy/hid.c
@@ -36,6 +36,7 @@
36 * the runtime footprint, and giving us at least some parts of what 36 * the runtime footprint, and giving us at least some parts of what
37 * a "gcc --combine ... part1.c part2.c part3.c ... " build would. 37 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
38 */ 38 */
39#define USBF_HID_INCLUDED
39#include "f_hid.c" 40#include "f_hid.c"
40 41
41 42