Skip to content

Commit

Permalink
usb: gadget: f_midi: convert to new function interface with backward …
Browse files Browse the repository at this point in the history
…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>
  • Loading branch information
Andrzej Pietrasiewicz authored and Felipe Balbi committed Nov 5, 2014
1 parent d23b4c3 commit b85e9de
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 6 deletions.
3 changes: 3 additions & 0 deletions drivers/usb/gadget/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ config USB_F_UAC2
config USB_F_UVC
tristate

config USB_F_MIDI
tristate

choice
tristate "USB Gadget Drivers"
default USB_ETH
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/gadget/function/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ usb_f_uac2-y := 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
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
147 changes: 141 additions & 6 deletions drivers/usb/gadget/function/f_midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>

Expand All @@ -33,6 +34,7 @@
#include <linux/usb/midi.h>

#include "u_f.h"
#include "u_midi.h"

MODULE_AUTHOR("Ben Williamson");
MODULE_LICENSE("GPL v2");
Expand Down Expand Up @@ -99,7 +101,7 @@ DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);

/* 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,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
Expand All @@ -110,7 +112,7 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = {
};

/* 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),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER,
Expand All @@ -121,7 +123,7 @@ static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = {
};

/* 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,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
Expand All @@ -132,7 +134,7 @@ static struct usb_interface_descriptor ms_interface_desc __initdata = {
};

/* 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,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER,
Expand Down Expand Up @@ -387,6 +389,7 @@ static void f_midi_disable(struct usb_function *f)
usb_ep_disable(midi->out_ep);
}

#ifdef USBF_MIDI_INCLUDED
static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = f->config->cdev;
Expand All @@ -409,6 +412,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
usb_free_all_descriptors(f);
kfree(midi);
}
#endif

static int f_midi_snd_free(struct snd_device *device)
{
Expand Down Expand Up @@ -729,8 +733,7 @@ static int f_midi_register_card(struct f_midi *midi)

/* MIDI function driver setup/binding */

static int __init
f_midi_bind(struct usb_configuration *c, struct usb_function *f)
static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_descriptor_header **midi_function;
struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
Expand All @@ -741,6 +744,14 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
struct f_midi *midi = func_to_midi(f);
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 */
if (midi_string_defs[0].id == 0) {
status = usb_string_id(c->cdev);
Expand Down Expand Up @@ -897,6 +908,10 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
kfree(midi_function);
usb_free_descriptors(f->hs_descriptors);
fail:
#ifndef USBF_MIDI_INCLUDED
f_midi_unregister_card(midi);
fail_register:
#endif
/* we might as well release our claims on endpoints */
if (midi->out_ep)
midi->out_ep->driver_data = NULL;
Expand All @@ -908,6 +923,7 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}

#ifdef USBF_MIDI_INCLUDED
/**
* f_midi_bind_config - add USB MIDI function to a configuration
* @c: the configuration to supcard the USB audio function
Expand Down Expand Up @@ -997,3 +1013,122 @@ int __init f_midi_bind_config(struct usb_configuration *c,
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 changes: 32 additions & 0 deletions drivers/usb/gadget/function/u_midi.h
Original file line number Diff line number Diff line change
@@ -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 */

1 change: 1 addition & 0 deletions drivers/usb/gadget/legacy/gmidi.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include "gadget_chips.h"

#define USBF_MIDI_INCLUDED
#include "f_midi.c"

/*-------------------------------------------------------------------------*/
Expand Down

0 comments on commit b85e9de

Please sign in to comment.