Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -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
+2 −0
Original line number Original line Diff line number Diff line
@@ -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
+141 −6
Original line number Original line Diff line number Diff line
@@ -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 @@
#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);
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 = {
};
};


/* 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 = {
};
};


/* 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 = {
};
};


/* 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)
	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)
	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)


/* 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)
	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)
	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)
	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,
	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
+32 −0
Original line number Original line Diff line number Diff line
/*
 * 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 */
+1 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@


#include "gadget_chips.h"
#include "gadget_chips.h"


#define USBF_MIDI_INCLUDED
#include "f_midi.c"
#include "f_midi.c"


/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/