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

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

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



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

This patch converts the f_uac1.c to the new function interface.

The file is now compiled into a separate usb_f_uac1.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.

Tested-by: default avatarSebastian Reimers <sebastian.reimers@googlemail.com>
Signed-off-by: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent af1a58ca
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -181,6 +181,9 @@ config USB_F_MASS_STORAGE
config USB_F_FS
	tristate

config USB_F_UAC1
	tristate

config USB_F_UAC2
	tristate

+2 −0
Original line number Diff line number Diff line
@@ -32,5 +32,7 @@ usb_f_mass_storage-y := f_mass_storage.o storage_common.o
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
usb_f_fs-y			:= f_fs.o
obj-$(CONFIG_USB_F_FS)		+= usb_f_fs.o
usb_f_uac1-y			:= f_uac1.o u_uac1.o
obj-$(CONFIG_USB_F_UAC1)	+= usb_f_uac1.o
usb_f_uac2-y			:= f_uac2.o
obj-$(CONFIG_USB_F_UAC2)	+= usb_f_uac2.o
+143 −26
Original line number Diff line number Diff line
@@ -11,13 +11,17 @@

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

#include "u_uac1.h"
#ifdef USBF_UAC1_INCLUDED
#include "u_uac1.c"
#endif

#define OUT_EP_MAX_PACKET_SIZE	200
#ifdef USBF_UAC1_INCLUDED
static int req_buf_size = OUT_EP_MAX_PACKET_SIZE;
module_param(req_buf_size, int, S_IRUGO);
MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size");
@@ -29,6 +33,7 @@ MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count");
static int audio_buf_size = 48000;
module_param(audio_buf_size, int, S_IRUGO);
MODULE_PARM_DESC(audio_buf_size, "Audio buffer size");
#endif

static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value);
static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
@@ -47,7 +52,7 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
#define F_AUDIO_NUM_INTERFACES	2

/* 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,
	.bNumEndpoints =	0,
@@ -189,7 +194,7 @@ static struct usb_endpoint_descriptor as_out_ep_desc = {
};

/* Class-specific AS ISO OUT Endpoint Descriptor */
static struct uac_iso_endpoint_descriptor as_iso_out_desc __initdata = {
static struct uac_iso_endpoint_descriptor as_iso_out_desc = {
	.bLength =		UAC_ISO_ENDPOINT_DESC_SIZE,
	.bDescriptorType =	USB_DT_CS_ENDPOINT,
	.bDescriptorSubtype =	UAC_EP_GENERAL,
@@ -198,7 +203,7 @@ static struct uac_iso_endpoint_descriptor as_iso_out_desc __initdata = {
	.wLockDelay =		__constant_cpu_to_le16(1),
};

static struct usb_descriptor_header *f_audio_desc[] __initdata = {
static struct usb_descriptor_header *f_audio_desc[] = {
	(struct usb_descriptor_header *)&ac_interface_desc,
	(struct usb_descriptor_header *)&ac_header_desc,

@@ -332,8 +337,17 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
	struct f_audio *audio = req->context;
	struct usb_composite_dev *cdev = audio->card.func.config->cdev;
	struct f_audio_buf *copy_buf = audio->copy_buf;
#ifndef USBF_UAC1_INCLUDED
	struct f_uac1_opts *opts;
	int audio_buf_size;
#endif
	int err;

#ifndef USBF_UAC1_INCLUDED
	opts = container_of(audio->card.func.fi, struct f_uac1_opts,
			    func_inst);
	audio_buf_size = opts->audio_buf_size;
#endif
	if (!copy_buf)
		return -EINVAL;

@@ -578,10 +592,21 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
	struct usb_composite_dev *cdev = f->config->cdev;
	struct usb_ep *out_ep = audio->out_ep;
	struct usb_request *req;
#ifndef USBF_UAC1_INCLUDED
	struct f_uac1_opts *opts;
	int req_buf_size, req_count, audio_buf_size;
#endif
	int i = 0, err = 0;

	DBG(cdev, "intf %d, alt %d\n", intf, alt);

#ifndef USBF_UAC1_INCLUDED
	opts = container_of(f->fi, struct f_uac1_opts, func_inst);
	req_buf_size = opts->req_buf_size;
	req_count = opts->req_count;
	audio_buf_size = opts->audio_buf_size;

#endif
	if (intf == 1) {
		if (alt == 1) {
			usb_ep_enable(out_ep);
@@ -657,13 +682,50 @@ static void f_audio_build_desc(struct f_audio *audio)
}

/* audio function driver setup/binding */
static int __init
static int
f_audio_bind(struct usb_configuration *c, struct usb_function *f)
{
	struct usb_composite_dev *cdev = c->cdev;
	struct f_audio		*audio = func_to_audio(f);
	int			status;
	struct usb_ep		*ep = NULL;
#ifndef USBF_UAC1_INCLUDED
	struct f_uac1_opts	*audio_opts;

	audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst);
	audio->card.gadget = c->cdev->gadget;
	audio_opts->card = &audio->card;
	/* set up ASLA audio devices */
	if (!audio_opts->bound) {
		status = gaudio_setup(&audio->card);
		if (status < 0)
			return status;
		audio_opts->bound = true;
	}
#else
	audio->card.gadget = c->cdev->gadget;
#endif
	if (strings_uac1[0].id == 0) {
		status = usb_string_ids_tab(c->cdev, strings_uac1);
		if (status < 0)
#ifdef USBF_UAC1_INCLUDED
			return status;
#else
			goto fail;
#endif
		ac_interface_desc.iInterface = strings_uac1[STR_AC_IF].id;
		input_terminal_desc.iTerminal =
			strings_uac1[STR_INPUT_TERMINAL].id;
		input_terminal_desc.iChannelNames =
			strings_uac1[STR_INPUT_TERMINAL_CH_NAMES].id;
		feature_unit_desc.iFeature = strings_uac1[STR_FEAT_DESC_0].id;
		output_terminal_desc.iTerminal =
			strings_uac1[STR_OUTPUT_TERMINAL].id;
		as_interface_alt_0_desc.iInterface =
			strings_uac1[STR_AS_IF_ALT0].id;
		as_interface_alt_1_desc.iInterface =
			strings_uac1[STR_AS_IF_ALT1].id;
	}

	f_audio_build_desc(audio);

@@ -698,19 +760,24 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
	return 0;

fail:
#ifndef USBF_UAC1_INCLUDED
	gaudio_cleanup(&audio->card);
#endif
	if (ep)
		ep->driver_data = NULL;
	return status;
}

#ifdef USBF_UAC1_INCLUDED
static void
f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
old_f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
{
	struct f_audio		*audio = func_to_audio(f);

	usb_free_all_descriptors(f);
	kfree(audio);
}
#endif

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

@@ -727,7 +794,7 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd)
}

/* Todo: add more control selecotor dynamically */
static int __init control_selector_init(struct f_audio *audio)
static int control_selector_init(struct f_audio *audio)
{
	INIT_LIST_HEAD(&audio->cs);
	list_add(&feature_unit.list, &audio->cs);
@@ -744,6 +811,7 @@ static int __init control_selector_init(struct f_audio *audio)
	return 0;
}

#ifdef USBF_UAC1_INCLUDED
/**
 * audio_bind_config - add USB audio function to a configuration
 * @c: the configuration to supcard the USB audio function
@@ -756,24 +824,6 @@ static int __init audio_bind_config(struct usb_configuration *c)
	struct f_audio *audio;
	int status;

	if (strings_uac1[0].id == 0) {
		status = usb_string_ids_tab(c->cdev, strings_uac1);
		if (status < 0)
			return status;
		ac_interface_desc.iInterface = strings_uac1[STR_AC_IF].id;
		input_terminal_desc.iTerminal =
			strings_uac1[STR_INPUT_TERMINAL].id;
		input_terminal_desc.iChannelNames =
			strings_uac1[STR_INPUT_TERMINAL_CH_NAMES].id;
		feature_unit_desc.iFeature = strings_uac1[STR_FEAT_DESC_0].id;
		output_terminal_desc.iTerminal =
			strings_uac1[STR_OUTPUT_TERMINAL].id;
		as_interface_alt_0_desc.iInterface =
			strings_uac1[STR_AS_IF_ALT0].id;
		as_interface_alt_1_desc.iInterface =
			strings_uac1[STR_AS_IF_ALT1].id;
	}

	/* allocate and initialize one new instance */
	audio = kzalloc(sizeof *audio, GFP_KERNEL);
	if (!audio)
@@ -789,10 +839,9 @@ static int __init audio_bind_config(struct usb_configuration *c)
	status = gaudio_setup(&audio->card);
	if (status < 0)
		goto setup_fail;

	audio->card.func.strings = uac1_strings;
	audio->card.func.bind = f_audio_bind;
	audio->card.func.unbind = f_audio_unbind;
	audio->card.func.unbind = old_f_audio_unbind;
	audio->card.func.set_alt = f_audio_set_alt;
	audio->card.func.setup = f_audio_setup;
	audio->card.func.disable = f_audio_disable;
@@ -816,3 +865,71 @@ setup_fail:
	kfree(audio);
	return status;
}
#else
static void f_audio_free_inst(struct usb_function_instance *f)
{
	struct f_uac1_opts *opts;

	opts = container_of(f, struct f_uac1_opts, func_inst);
	gaudio_cleanup(opts->card);
	kfree(opts);
}

static struct usb_function_instance *f_audio_alloc_inst(void)
{
	struct f_uac1_opts *opts;

	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
	if (!opts)
		return ERR_PTR(-ENOMEM);

	opts->func_inst.free_func_inst = f_audio_free_inst;

	return &opts->func_inst;
}

static void f_audio_free(struct usb_function *f)
{
	struct f_audio *audio = func_to_audio(f);

	kfree(audio);
}

static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
{
	usb_free_all_descriptors(f);
}

static struct usb_function *f_audio_alloc(struct usb_function_instance *fi)
{
	struct f_audio *audio;

	/* allocate and initialize one new instance */
	audio = kzalloc(sizeof(*audio), GFP_KERNEL);
	if (!audio)
		return ERR_PTR(-ENOMEM);

	audio->card.func.name = "g_audio";

	INIT_LIST_HEAD(&audio->play_queue);
	spin_lock_init(&audio->lock);

	audio->card.func.strings = uac1_strings;
	audio->card.func.bind = f_audio_bind;
	audio->card.func.unbind = f_audio_unbind;
	audio->card.func.set_alt = f_audio_set_alt;
	audio->card.func.setup = f_audio_setup;
	audio->card.func.disable = f_audio_disable;
	audio->card.func.free_func = f_audio_free;

	control_selector_init(audio);

	INIT_WORK(&audio->playback_work, f_audio_playback_work);

	return &audio->card.func;
}

DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bryan Wu");
#endif
+26 −5
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/delay.h>
@@ -23,6 +24,7 @@
 * This component encapsulates the ALSA devices for USB audio gadget
 */

#ifdef USBF_UAC1_INCLUDED
#define FILE_PCM_PLAYBACK	"/dev/snd/pcmC0D0p"
#define FILE_PCM_CAPTURE	"/dev/snd/pcmC0D0c"
#define FILE_CONTROL		"/dev/snd/controlC0"
@@ -38,7 +40,7 @@ MODULE_PARM_DESC(fn_cap, "Capture PCM device file name");
static char *fn_cntl = FILE_CONTROL;
module_param(fn_cntl, charp, S_IRUGO);
MODULE_PARM_DESC(fn_cntl, "Control device file name");

#endif
/*-------------------------------------------------------------------------*/

/**
@@ -167,7 +169,7 @@ static int playback_default_hw_params(struct gaudio_snd_dev *snd)
/**
 * Playback audio buffer data by ALSA PCM device
 */
static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
{
	struct gaudio_snd_dev	*snd = &card->playback;
	struct snd_pcm_substream *substream = snd->substream;
@@ -202,12 +204,12 @@ try_again:
	return 0;
}

static int u_audio_get_playback_channels(struct gaudio *card)
int u_audio_get_playback_channels(struct gaudio *card)
{
	return card->playback.channels;
}

static int u_audio_get_playback_rate(struct gaudio *card)
int u_audio_get_playback_rate(struct gaudio *card)
{
	return card->playback.rate;
}
@@ -220,6 +222,15 @@ static int gaudio_open_snd_dev(struct gaudio *card)
{
	struct snd_pcm_file *pcm_file;
	struct gaudio_snd_dev *snd;
#ifndef USBF_UAC1_INCLUDED
	struct f_uac1_opts *opts;
	char *fn_play, *fn_cap, *fn_cntl;

	opts = container_of(card->func.fi, struct f_uac1_opts, func_inst);
	fn_play = opts->fn_play;
	fn_cap = opts->fn_cap;
	fn_cntl = opts->fn_cntl;
#endif

	if (!card)
		return -ENODEV;
@@ -293,7 +304,9 @@ static int gaudio_close_snd_dev(struct gaudio *gau)
	return 0;
}

#ifdef USBF_UAC1_INCLUDED
static struct gaudio *the_card;
#endif
/**
 * gaudio_setup - setup ALSA interface and preparing for USB transfer
 *
@@ -301,15 +314,17 @@ static struct gaudio *the_card;
 *
 * Returns negative errno, or zero on success
 */
int __init gaudio_setup(struct gaudio *card)
int gaudio_setup(struct gaudio *card)
{
	int	ret;

	ret = gaudio_open_snd_dev(card);
	if (ret)
		ERROR(card, "we need at least one control device\n");
#ifdef USBF_UAC1_INCLUDED
	else if (!the_card)
		the_card = card;
#endif

	return ret;

@@ -320,11 +335,17 @@ int __init gaudio_setup(struct gaudio *card)
 *
 * This is called to free all resources allocated by @gaudio_setup().
 */
#ifdef USBF_UAC1_INCLUDED
void gaudio_cleanup(void)
#else
void gaudio_cleanup(struct gaudio *the_card)
#endif
{
	if (the_card) {
		gaudio_close_snd_dev(the_card);
#ifdef USBF_UAC1_INCLUDED
		the_card = NULL;
#endif
	}
}
+20 −0
Original line number Diff line number Diff line
@@ -50,7 +50,27 @@ struct gaudio {
	/* TODO */
};

struct f_uac1_opts {
	struct usb_function_instance	func_inst;
	int				req_buf_size;
	int				req_count;
	int				audio_buf_size;
	char				*fn_play;
	char				*fn_cap;
	char				*fn_cntl;
	bool				bound;
	struct gaudio			*card;
};

int gaudio_setup(struct gaudio *card);
#ifdef USBF_UAC1_INCLUDED
void gaudio_cleanup(void);
#else
void gaudio_cleanup(struct gaudio *the_card);
#endif

size_t u_audio_playback(struct gaudio *card, void *buf, size_t count);
int u_audio_get_playback_channels(struct gaudio *card);
int u_audio_get_playback_rate(struct gaudio *card);

#endif /* __U_AUDIO_H */
Loading