aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/function/f_midi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/function/f_midi.c')
-rw-r--r--drivers/usb/gadget/function/f_midi.c364
1 files changed, 274 insertions, 90 deletions
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 807b31c0edc3..a90440300735 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/module.h>
23#include <linux/slab.h> 24#include <linux/slab.h>
24#include <linux/device.h> 25#include <linux/device.h>
25 26
@@ -33,6 +34,7 @@
33#include <linux/usb/midi.h> 34#include <linux/usb/midi.h>
34 35
35#include "u_f.h" 36#include "u_f.h"
37#include "u_midi.h"
36 38
37MODULE_AUTHOR("Ben Williamson"); 39MODULE_AUTHOR("Ben Williamson");
38MODULE_LICENSE("GPL v2"); 40MODULE_LICENSE("GPL v2");
@@ -99,7 +101,7 @@ DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
99DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16); 101DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
100 102
101/* B.3.1 Standard AC Interface Descriptor */ 103/* B.3.1 Standard AC Interface Descriptor */
102static struct usb_interface_descriptor ac_interface_desc __initdata = { 104static struct usb_interface_descriptor ac_interface_desc = {
103 .bLength = USB_DT_INTERFACE_SIZE, 105 .bLength = USB_DT_INTERFACE_SIZE,
104 .bDescriptorType = USB_DT_INTERFACE, 106 .bDescriptorType = USB_DT_INTERFACE,
105 /* .bInterfaceNumber = DYNAMIC */ 107 /* .bInterfaceNumber = DYNAMIC */
@@ -110,7 +112,7 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = {
110}; 112};
111 113
112/* B.3.2 Class-Specific AC Interface Descriptor */ 114/* B.3.2 Class-Specific AC Interface Descriptor */
113static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = { 115static struct uac1_ac_header_descriptor_1 ac_header_desc = {
114 .bLength = UAC_DT_AC_HEADER_SIZE(1), 116 .bLength = UAC_DT_AC_HEADER_SIZE(1),
115 .bDescriptorType = USB_DT_CS_INTERFACE, 117 .bDescriptorType = USB_DT_CS_INTERFACE,
116 .bDescriptorSubtype = USB_MS_HEADER, 118 .bDescriptorSubtype = USB_MS_HEADER,
@@ -121,7 +123,7 @@ static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = {
121}; 123};
122 124
123/* B.4.1 Standard MS Interface Descriptor */ 125/* B.4.1 Standard MS Interface Descriptor */
124static struct usb_interface_descriptor ms_interface_desc __initdata = { 126static struct usb_interface_descriptor ms_interface_desc = {
125 .bLength = USB_DT_INTERFACE_SIZE, 127 .bLength = USB_DT_INTERFACE_SIZE,
126 .bDescriptorType = USB_DT_INTERFACE, 128 .bDescriptorType = USB_DT_INTERFACE,
127 /* .bInterfaceNumber = DYNAMIC */ 129 /* .bInterfaceNumber = DYNAMIC */
@@ -132,7 +134,7 @@ static struct usb_interface_descriptor ms_interface_desc __initdata = {
132}; 134};
133 135
134/* B.4.2 Class-Specific MS Interface Descriptor */ 136/* B.4.2 Class-Specific MS Interface Descriptor */
135static struct usb_ms_header_descriptor ms_header_desc __initdata = { 137static struct usb_ms_header_descriptor ms_header_desc = {
136 .bLength = USB_DT_MS_HEADER_SIZE, 138 .bLength = USB_DT_MS_HEADER_SIZE,
137 .bDescriptorType = USB_DT_CS_INTERFACE, 139 .bDescriptorType = USB_DT_CS_INTERFACE,
138 .bDescriptorSubtype = USB_MS_HEADER, 140 .bDescriptorSubtype = USB_MS_HEADER,
@@ -387,29 +389,6 @@ static void f_midi_disable(struct usb_function *f)
387 usb_ep_disable(midi->out_ep); 389 usb_ep_disable(midi->out_ep);
388} 390}
389 391
390static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
391{
392 struct usb_composite_dev *cdev = f->config->cdev;
393 struct f_midi *midi = func_to_midi(f);
394 struct snd_card *card;
395
396 DBG(cdev, "unbind\n");
397
398 /* just to be sure */
399 f_midi_disable(f);
400
401 card = midi->card;
402 midi->card = NULL;
403 if (card)
404 snd_card_free(card);
405
406 kfree(midi->id);
407 midi->id = NULL;
408
409 usb_free_all_descriptors(f);
410 kfree(midi);
411}
412
413static int f_midi_snd_free(struct snd_device *device) 392static int f_midi_snd_free(struct snd_device *device)
414{ 393{
415 return 0; 394 return 0;
@@ -654,6 +633,14 @@ static struct snd_rawmidi_ops gmidi_out_ops = {
654 .trigger = f_midi_out_trigger 633 .trigger = f_midi_out_trigger
655}; 634};
656 635
636static inline void f_midi_unregister_card(struct f_midi *midi)
637{
638 if (midi->card) {
639 snd_card_free(midi->card);
640 midi->card = NULL;
641 }
642}
643
657/* register as a sound "card" */ 644/* register as a sound "card" */
658static int f_midi_register_card(struct f_midi *midi) 645static int f_midi_register_card(struct f_midi *midi)
659{ 646{
@@ -715,17 +702,13 @@ static int f_midi_register_card(struct f_midi *midi)
715 return 0; 702 return 0;
716 703
717fail: 704fail:
718 if (midi->card) { 705 f_midi_unregister_card(midi);
719 snd_card_free(midi->card);
720 midi->card = NULL;
721 }
722 return err; 706 return err;
723} 707}
724 708
725/* MIDI function driver setup/binding */ 709/* MIDI function driver setup/binding */
726 710
727static int __init 711static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
728f_midi_bind(struct usb_configuration *c, struct usb_function *f)
729{ 712{
730 struct usb_descriptor_header **midi_function; 713 struct usb_descriptor_header **midi_function;
731 struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS]; 714 struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
@@ -734,15 +717,23 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
734 struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS]; 717 struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS];
735 struct usb_composite_dev *cdev = c->cdev; 718 struct usb_composite_dev *cdev = c->cdev;
736 struct f_midi *midi = func_to_midi(f); 719 struct f_midi *midi = func_to_midi(f);
720 struct usb_string *us;
737 int status, n, jack = 1, i = 0; 721 int status, n, jack = 1, i = 0;
738 722
723 midi->gadget = cdev->gadget;
724 tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
725 status = f_midi_register_card(midi);
726 if (status < 0)
727 goto fail_register;
728
739 /* maybe allocate device-global string ID */ 729 /* maybe allocate device-global string ID */
740 if (midi_string_defs[0].id == 0) { 730 us = usb_gstrings_attach(c->cdev, midi_strings,
741 status = usb_string_id(c->cdev); 731 ARRAY_SIZE(midi_string_defs));
742 if (status < 0) 732 if (IS_ERR(us)) {
743 goto fail; 733 status = PTR_ERR(us);
744 midi_string_defs[0].id = status; 734 goto fail;
745 } 735 }
736 ac_interface_desc.iInterface = us[STRING_FUNC_IDX].id;
746 737
747 /* We have two interfaces, AudioControl and MIDIStreaming */ 738 /* We have two interfaces, AudioControl and MIDIStreaming */
748 status = usb_interface_id(c, f); 739 status = usb_interface_id(c, f);
@@ -892,6 +883,8 @@ fail_f_midi:
892 kfree(midi_function); 883 kfree(midi_function);
893 usb_free_descriptors(f->hs_descriptors); 884 usb_free_descriptors(f->hs_descriptors);
894fail: 885fail:
886 f_midi_unregister_card(midi);
887fail_register:
895 /* we might as well release our claims on endpoints */ 888 /* we might as well release our claims on endpoints */
896 if (midi->out_ep) 889 if (midi->out_ep)
897 midi->out_ep->driver_data = NULL; 890 midi->out_ep->driver_data = NULL;
@@ -903,42 +896,235 @@ fail:
903 return status; 896 return status;
904} 897}
905 898
906/** 899static inline struct f_midi_opts *to_f_midi_opts(struct config_item *item)
907 * f_midi_bind_config - add USB MIDI function to a configuration 900{
908 * @c: the configuration to supcard the USB audio function 901 return container_of(to_config_group(item), struct f_midi_opts,
909 * @index: the soundcard index to use for the ALSA device creation 902 func_inst.group);
910 * @id: the soundcard id to use for the ALSA device creation 903}
911 * @buflen: the buffer length to use 904
912 * @qlen the number of read requests to pre-allocate 905CONFIGFS_ATTR_STRUCT(f_midi_opts);
913 * Context: single threaded during gadget setup 906CONFIGFS_ATTR_OPS(f_midi_opts);
914 * 907
915 * Returns zero on success, else negative errno. 908static void midi_attr_release(struct config_item *item)
916 */ 909{
917int __init f_midi_bind_config(struct usb_configuration *c, 910 struct f_midi_opts *opts = to_f_midi_opts(item);
918 int index, char *id, 911
919 unsigned int in_ports, 912 usb_put_function_instance(&opts->func_inst);
920 unsigned int out_ports, 913}
921 unsigned int buflen, 914
922 unsigned int qlen) 915static struct configfs_item_operations midi_item_ops = {
916 .release = midi_attr_release,
917 .show_attribute = f_midi_opts_attr_show,
918 .store_attribute = f_midi_opts_attr_store,
919};
920
921#define F_MIDI_OPT(name, test_limit, limit) \
922static ssize_t f_midi_opts_##name##_show(struct f_midi_opts *opts, char *page) \
923{ \
924 int result; \
925 \
926 mutex_lock(&opts->lock); \
927 result = sprintf(page, "%d\n", opts->name); \
928 mutex_unlock(&opts->lock); \
929 \
930 return result; \
931} \
932 \
933static ssize_t f_midi_opts_##name##_store(struct f_midi_opts *opts, \
934 const char *page, size_t len) \
935{ \
936 int ret; \
937 u32 num; \
938 \
939 mutex_lock(&opts->lock); \
940 if (opts->refcnt) { \
941 ret = -EBUSY; \
942 goto end; \
943 } \
944 \
945 ret = kstrtou32(page, 0, &num); \
946 if (ret) \
947 goto end; \
948 \
949 if (test_limit && num > limit) { \
950 ret = -EINVAL; \
951 goto end; \
952 } \
953 opts->name = num; \
954 ret = len; \
955 \
956end: \
957 mutex_unlock(&opts->lock); \
958 return ret; \
959} \
960 \
961static struct f_midi_opts_attribute f_midi_opts_##name = \
962 __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_midi_opts_##name##_show, \
963 f_midi_opts_##name##_store)
964
965F_MIDI_OPT(index, true, SNDRV_CARDS);
966F_MIDI_OPT(buflen, false, 0);
967F_MIDI_OPT(qlen, false, 0);
968F_MIDI_OPT(in_ports, true, MAX_PORTS);
969F_MIDI_OPT(out_ports, true, MAX_PORTS);
970
971static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page)
972{
973 int result;
974
975 mutex_lock(&opts->lock);
976 result = strlcpy(page, opts->id, PAGE_SIZE);
977 mutex_unlock(&opts->lock);
978
979 return result;
980}
981
982static ssize_t f_midi_opts_id_store(struct f_midi_opts *opts,
983 const char *page, size_t len)
984{
985 int ret;
986 char *c;
987
988 mutex_lock(&opts->lock);
989 if (opts->refcnt) {
990 ret = -EBUSY;
991 goto end;
992 }
993
994 c = kstrndup(page, len, GFP_KERNEL);
995 if (!c) {
996 ret = -ENOMEM;
997 goto end;
998 }
999 if (opts->id_allocated)
1000 kfree(opts->id);
1001 opts->id = c;
1002 opts->id_allocated = true;
1003 ret = len;
1004end:
1005 mutex_unlock(&opts->lock);
1006 return ret;
1007}
1008
1009static struct f_midi_opts_attribute f_midi_opts_id =
1010 __CONFIGFS_ATTR(id, S_IRUGO | S_IWUSR, f_midi_opts_id_show,
1011 f_midi_opts_id_store);
1012
1013static struct configfs_attribute *midi_attrs[] = {
1014 &f_midi_opts_index.attr,
1015 &f_midi_opts_buflen.attr,
1016 &f_midi_opts_qlen.attr,
1017 &f_midi_opts_in_ports.attr,
1018 &f_midi_opts_out_ports.attr,
1019 &f_midi_opts_id.attr,
1020 NULL,
1021};
1022
1023static struct config_item_type midi_func_type = {
1024 .ct_item_ops = &midi_item_ops,
1025 .ct_attrs = midi_attrs,
1026 .ct_owner = THIS_MODULE,
1027};
1028
1029static void f_midi_free_inst(struct usb_function_instance *f)
1030{
1031 struct f_midi_opts *opts;
1032
1033 opts = container_of(f, struct f_midi_opts, func_inst);
1034
1035 if (opts->id_allocated)
1036 kfree(opts->id);
1037
1038 kfree(opts);
1039}
1040
1041static struct usb_function_instance *f_midi_alloc_inst(void)
1042{
1043 struct f_midi_opts *opts;
1044
1045 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
1046 if (!opts)
1047 return ERR_PTR(-ENOMEM);
1048
1049 mutex_init(&opts->lock);
1050 opts->func_inst.free_func_inst = f_midi_free_inst;
1051 opts->index = SNDRV_DEFAULT_IDX1;
1052 opts->id = SNDRV_DEFAULT_STR1;
1053 opts->buflen = 256;
1054 opts->qlen = 32;
1055 opts->in_ports = 1;
1056 opts->out_ports = 1;
1057
1058 config_group_init_type_name(&opts->func_inst.group, "",
1059 &midi_func_type);
1060
1061 return &opts->func_inst;
1062}
1063
1064static void f_midi_free(struct usb_function *f)
1065{
1066 struct f_midi *midi;
1067 struct f_midi_opts *opts;
1068 int i;
1069
1070 midi = func_to_midi(f);
1071 opts = container_of(f->fi, struct f_midi_opts, func_inst);
1072 kfree(midi->id);
1073 mutex_lock(&opts->lock);
1074 for (i = opts->in_ports - 1; i >= 0; --i)
1075 kfree(midi->in_port[i]);
1076 kfree(midi);
1077 --opts->refcnt;
1078 mutex_unlock(&opts->lock);
1079}
1080
1081static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
1082{
1083 struct usb_composite_dev *cdev = f->config->cdev;
1084 struct f_midi *midi = func_to_midi(f);
1085 struct snd_card *card;
1086
1087 DBG(cdev, "unbind\n");
1088
1089 /* just to be sure */
1090 f_midi_disable(f);
1091
1092 card = midi->card;
1093 midi->card = NULL;
1094 if (card)
1095 snd_card_free(card);
1096
1097 usb_free_all_descriptors(f);
1098}
1099
1100static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
923{ 1101{
924 struct f_midi *midi; 1102 struct f_midi *midi;
1103 struct f_midi_opts *opts;
925 int status, i; 1104 int status, i;
926 1105
1106 opts = container_of(fi, struct f_midi_opts, func_inst);
1107
1108 mutex_lock(&opts->lock);
927 /* sanity check */ 1109 /* sanity check */
928 if (in_ports > MAX_PORTS || out_ports > MAX_PORTS) 1110 if (opts->in_ports > MAX_PORTS || opts->out_ports > MAX_PORTS) {
929 return -EINVAL; 1111 mutex_unlock(&opts->lock);
1112 return ERR_PTR(-EINVAL);
1113 }
930 1114
931 /* allocate and initialize one new instance */ 1115 /* allocate and initialize one new instance */
932 midi = kzalloc(sizeof *midi, GFP_KERNEL); 1116 midi = kzalloc(sizeof(*midi), GFP_KERNEL);
933 if (!midi) { 1117 if (!midi) {
934 status = -ENOMEM; 1118 mutex_unlock(&opts->lock);
935 goto fail; 1119 return ERR_PTR(-ENOMEM);
936 } 1120 }
937 1121
938 for (i = 0; i < in_ports; i++) { 1122 for (i = 0; i < opts->in_ports; i++) {
939 struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL); 1123 struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL);
1124
940 if (!port) { 1125 if (!port) {
941 status = -ENOMEM; 1126 status = -ENOMEM;
1127 mutex_unlock(&opts->lock);
942 goto setup_fail; 1128 goto setup_fail;
943 } 1129 }
944 1130
@@ -948,39 +1134,37 @@ int __init f_midi_bind_config(struct usb_configuration *c,
948 midi->in_port[i] = port; 1134 midi->in_port[i] = port;
949 } 1135 }
950 1136
951 midi->gadget = c->cdev->gadget;
952 tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
953
954 /* set up ALSA midi devices */ 1137 /* set up ALSA midi devices */
955 midi->in_ports = in_ports; 1138 midi->id = kstrdup(opts->id, GFP_KERNEL);
956 midi->out_ports = out_ports; 1139 if (opts->id && !midi->id) {
957 status = f_midi_register_card(midi); 1140 status = -ENOMEM;
958 if (status < 0) 1141 mutex_unlock(&opts->lock);
959 goto setup_fail; 1142 goto kstrdup_fail;
960 1143 }
961 midi->func.name = "gmidi function"; 1144 midi->in_ports = opts->in_ports;
962 midi->func.strings = midi_strings; 1145 midi->out_ports = opts->out_ports;
963 midi->func.bind = f_midi_bind; 1146 midi->index = opts->index;
964 midi->func.unbind = f_midi_unbind; 1147 midi->buflen = opts->buflen;
965 midi->func.set_alt = f_midi_set_alt; 1148 midi->qlen = opts->qlen;
966 midi->func.disable = f_midi_disable; 1149 ++opts->refcnt;
967 1150 mutex_unlock(&opts->lock);
968 midi->id = kstrdup(id, GFP_KERNEL); 1151
969 midi->index = index; 1152 midi->func.name = "gmidi function";
970 midi->buflen = buflen; 1153 midi->func.bind = f_midi_bind;
971 midi->qlen = qlen; 1154 midi->func.unbind = f_midi_unbind;
972 1155 midi->func.set_alt = f_midi_set_alt;
973 status = usb_add_function(c, &midi->func); 1156 midi->func.disable = f_midi_disable;
974 if (status) 1157 midi->func.free_func = f_midi_free;
975 goto setup_fail; 1158
976 1159 return &midi->func;
977 return 0; 1160
978 1161kstrdup_fail:
1162 f_midi_unregister_card(midi);
979setup_fail: 1163setup_fail:
980 for (--i; i >= 0; i--) 1164 for (--i; i >= 0; i--)
981 kfree(midi->in_port[i]); 1165 kfree(midi->in_port[i]);
982 kfree(midi); 1166 kfree(midi);
983fail: 1167 return ERR_PTR(status);
984 return status;
985} 1168}
986 1169
1170DECLARE_USB_FUNCTION_INIT(midi, f_midi_alloc_inst, f_midi_alloc);