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: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
d23b4c3ee2
commit
b85e9de9e8
5 changed files with 179 additions and 6 deletions
|
@ -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
|
||||||
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 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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 @@ fail:
|
||||||
|
|
||||||
/* 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 @@ fail_f_midi:
|
||||||
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 @@ fail:
|
||||||
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 @@ fail:
|
||||||
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
drivers/usb/gadget/function/u_midi.h
Normal file
32
drivers/usb/gadget/function/u_midi.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
|
||||||
#include "gadget_chips.h"
|
#include "gadget_chips.h"
|
||||||
|
|
||||||
|
#define USBF_MIDI_INCLUDED
|
||||||
#include "f_midi.c"
|
#include "f_midi.c"
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue