Commit b85e9de9 authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Felipe Balbi

usb: gadget: f_midi: convert to new function interface with backward compatibility

Converting midi to the new function interface requires converting
the USB midi's function code and its users.

This patch converts the f_midi.c to the new function interface.
The file can now be compiled into a separate usb_f_midi.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: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent d23b4c3e
...@@ -190,6 +190,9 @@ config USB_F_UAC2 ...@@ -190,6 +190,9 @@ config USB_F_UAC2
config USB_F_UVC config USB_F_UVC
tristate tristate
config USB_F_MIDI
tristate
choice choice
tristate "USB Gadget Drivers" tristate "USB Gadget Drivers"
default USB_ETH default USB_ETH
......
...@@ -38,3 +38,5 @@ usb_f_uac2-y := f_uac2.o ...@@ -38,3 +38,5 @@ usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o
usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o
obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o
usb_f_midi-y := f_midi.o
obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
#include <linux/usb/midi.h> #include <linux/usb/midi.h>
#include "u_f.h" #include "u_f.h"
#include "u_midi.h"
MODULE_AUTHOR("Ben Williamson"); MODULE_AUTHOR("Ben Williamson");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -99,7 +101,7 @@ DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); ...@@ -99,7 +101,7 @@ DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16); DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
/* B.3.1 Standard AC Interface Descriptor */ /* B.3.1 Standard AC Interface Descriptor */
static struct usb_interface_descriptor ac_interface_desc __initdata = { static struct usb_interface_descriptor ac_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE, .bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */ /* .bInterfaceNumber = DYNAMIC */
...@@ -110,7 +112,7 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = { ...@@ -110,7 +112,7 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = {
}; };
/* B.3.2 Class-Specific AC Interface Descriptor */ /* B.3.2 Class-Specific AC Interface Descriptor */
static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = { static struct uac1_ac_header_descriptor_1 ac_header_desc = {
.bLength = UAC_DT_AC_HEADER_SIZE(1), .bLength = UAC_DT_AC_HEADER_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER, .bDescriptorSubtype = USB_MS_HEADER,
...@@ -121,7 +123,7 @@ static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = { ...@@ -121,7 +123,7 @@ static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = {
}; };
/* B.4.1 Standard MS Interface Descriptor */ /* B.4.1 Standard MS Interface Descriptor */
static struct usb_interface_descriptor ms_interface_desc __initdata = { static struct usb_interface_descriptor ms_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE, .bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */ /* .bInterfaceNumber = DYNAMIC */
...@@ -132,7 +134,7 @@ static struct usb_interface_descriptor ms_interface_desc __initdata = { ...@@ -132,7 +134,7 @@ static struct usb_interface_descriptor ms_interface_desc __initdata = {
}; };
/* B.4.2 Class-Specific MS Interface Descriptor */ /* B.4.2 Class-Specific MS Interface Descriptor */
static struct usb_ms_header_descriptor ms_header_desc __initdata = { static struct usb_ms_header_descriptor ms_header_desc = {
.bLength = USB_DT_MS_HEADER_SIZE, .bLength = USB_DT_MS_HEADER_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER, .bDescriptorSubtype = USB_MS_HEADER,
...@@ -387,6 +389,7 @@ static void f_midi_disable(struct usb_function *f) ...@@ -387,6 +389,7 @@ static void f_midi_disable(struct usb_function *f)
usb_ep_disable(midi->out_ep); usb_ep_disable(midi->out_ep);
} }
#ifdef USBF_MIDI_INCLUDED
static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
struct usb_composite_dev *cdev = f->config->cdev; struct usb_composite_dev *cdev = f->config->cdev;
...@@ -409,6 +412,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -409,6 +412,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
usb_free_all_descriptors(f); usb_free_all_descriptors(f);
kfree(midi); kfree(midi);
} }
#endif
static int f_midi_snd_free(struct snd_device *device) static int f_midi_snd_free(struct snd_device *device)
{ {
...@@ -729,8 +733,7 @@ static int f_midi_register_card(struct f_midi *midi) ...@@ -729,8 +733,7 @@ static int f_midi_register_card(struct f_midi *midi)
/* MIDI function driver setup/binding */ /* MIDI function driver setup/binding */
static int __init static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
f_midi_bind(struct usb_configuration *c, struct usb_function *f)
{ {
struct usb_descriptor_header **midi_function; struct usb_descriptor_header **midi_function;
struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS]; struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
...@@ -741,6 +744,14 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -741,6 +744,14 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
struct f_midi *midi = func_to_midi(f); struct f_midi *midi = func_to_midi(f);
int status, n, jack = 1, i = 0; int status, n, jack = 1, i = 0;
#ifndef USBF_MIDI_INCLUDED
midi->gadget = cdev->gadget;
tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
status = f_midi_register_card(midi);
if (status < 0)
goto fail_register;
#endif
/* maybe allocate device-global string ID */ /* maybe allocate device-global string ID */
if (midi_string_defs[0].id == 0) { if (midi_string_defs[0].id == 0) {
status = usb_string_id(c->cdev); status = usb_string_id(c->cdev);
...@@ -897,6 +908,10 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -897,6 +908,10 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
kfree(midi_function); kfree(midi_function);
usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->hs_descriptors);
fail: fail:
#ifndef USBF_MIDI_INCLUDED
f_midi_unregister_card(midi);
fail_register:
#endif
/* we might as well release our claims on endpoints */ /* we might as well release our claims on endpoints */
if (midi->out_ep) if (midi->out_ep)
midi->out_ep->driver_data = NULL; midi->out_ep->driver_data = NULL;
...@@ -908,6 +923,7 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -908,6 +923,7 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
return status; return status;
} }
#ifdef USBF_MIDI_INCLUDED
/** /**
* f_midi_bind_config - add USB MIDI function to a configuration * f_midi_bind_config - add USB MIDI function to a configuration
* @c: the configuration to supcard the USB audio function * @c: the configuration to supcard the USB audio function
...@@ -997,3 +1013,122 @@ int __init f_midi_bind_config(struct usb_configuration *c, ...@@ -997,3 +1013,122 @@ int __init f_midi_bind_config(struct usb_configuration *c,
return status; return status;
} }
#else
static void f_midi_free_inst(struct usb_function_instance *f)
{
struct f_midi_opts *opts;
opts = container_of(f, struct f_midi_opts, func_inst);
kfree(opts);
}
static struct usb_function_instance *f_midi_alloc_inst(void)
{
struct f_midi_opts *opts;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = f_midi_free_inst;
return &opts->func_inst;
}
static void f_midi_free(struct usb_function *f)
{
struct f_midi *midi;
struct f_midi_opts *opts;
int i;
midi = func_to_midi(f);
opts = container_of(f->fi, struct f_midi_opts, func_inst);
kfree(midi->id);
for (i = opts->in_ports - 1; i >= 0; --i)
kfree(midi->in_port[i]);
kfree(midi);
}
static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = f->config->cdev;
struct f_midi *midi = func_to_midi(f);
struct snd_card *card;
DBG(cdev, "unbind\n");
/* just to be sure */
f_midi_disable(f);
card = midi->card;
midi->card = NULL;
if (card)
snd_card_free(card);
usb_free_all_descriptors(f);
}
struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
{
struct f_midi *midi;
struct f_midi_opts *opts;
int status, i;
opts = container_of(fi, struct f_midi_opts, func_inst);
/* sanity check */
if (opts->in_ports > MAX_PORTS || opts->out_ports > MAX_PORTS)
return ERR_PTR(-EINVAL);
/* allocate and initialize one new instance */
midi = kzalloc(sizeof(*midi), GFP_KERNEL);
if (!midi)
return ERR_PTR(-ENOMEM);
for (i = 0; i < opts->in_ports; i++) {
struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL);
if (!port) {
status = -ENOMEM;
goto setup_fail;
}
port->midi = midi;
port->active = 0;
port->cable = i;
midi->in_port[i] = port;
}
/* set up ALSA midi devices */
midi->id = kstrdup(opts->id, GFP_KERNEL);
if (opts->id && !midi->id) {
status = -ENOMEM;
goto kstrdup_fail;
}
midi->in_ports = opts->in_ports;
midi->out_ports = opts->out_ports;
midi->index = opts->index;
midi->buflen = opts->buflen;
midi->qlen = opts->qlen;
midi->func.name = "gmidi function";
midi->func.strings = midi_strings;
midi->func.bind = f_midi_bind;
midi->func.unbind = f_midi_unbind;
midi->func.set_alt = f_midi_set_alt;
midi->func.disable = f_midi_disable;
midi->func.free_func = f_midi_free;
return &midi->func;
kstrdup_fail:
f_midi_unregister_card(midi);
setup_fail:
for (--i; i >= 0; i--)
kfree(midi->in_port[i]);
kfree(midi);
return ERR_PTR(status);
}
DECLARE_USB_FUNCTION_INIT(midi, f_midi_alloc_inst, f_midi_alloc);
#endif
/*
* u_midi.h
*
* Utility definitions for the midi function
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef U_MIDI_H
#define U_MIDI_H
#include <linux/usb/composite.h>
struct f_midi_opts {
struct usb_function_instance func_inst;
int index;
char *id;
unsigned int in_ports;
unsigned int out_ports;
unsigned int buflen;
unsigned int qlen;
};
#endif /* U_MIDI_H */
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "gadget_chips.h" #include "gadget_chips.h"
#define USBF_MIDI_INCLUDED
#include "f_midi.c" #include "f_midi.c"
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment