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

Commit 8e362602 authored by Manu Gautam's avatar Manu Gautam Committed by Sriharsha Allenki
Browse files

usb: android: f_uac2: Add support for UAC2 function



Integrate USB Audio class (UAC2) function driver with
android gadget. Unlike UAC1 driver, this exposes sound
card to allow playback/capture control from userspace.
While at it also fix issues related to composition
switch, and composite device enumeration that requires
updating bFirstIface for IAD descriptor

CRs-fixed: 1097689
Change-Id: I6ac8f3b5d9036a81bd2e82c558ff0f93090ce5a9
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent 087caba6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -423,6 +423,7 @@ config USB_G_ANDROID
	select USB_F_NCM
	select USB_F_MASS_STORAGE
	select USB_F_UAC1 if SND_PCM
	select USB_F_UAC2 if SND_PCM
	select USB_F_UVC if MEDIA_SUPPORT
	help
	  The Android Composite Gadget supports multiple USB
+59 −0
Original line number Diff line number Diff line
@@ -1514,6 +1514,64 @@ static struct android_usb_function audio_function = {
};
#endif

/* PERIPHERAL uac2 */
struct uac2_function_config {
	struct usb_function *func;
	struct usb_function_instance *fi;
};

static int uac2_function_init(struct android_usb_function *f,
			       struct usb_composite_dev *cdev)
{
	struct uac2_function_config *config;

	f->config = kzalloc(sizeof(*config), GFP_KERNEL);
	if (!f->config)
		return -ENOMEM;

	config = f->config;

	config->fi = usb_get_function_instance("uac2");
	if (IS_ERR(config->fi))
		return PTR_ERR(config->fi);

	config->func = usb_get_function(config->fi);
	if (IS_ERR(config->func)) {
		usb_put_function_instance(config->fi);
		return PTR_ERR(config->func);
	}

	return 0;
}

static void uac2_function_cleanup(struct android_usb_function *f)
{
	struct uac2_function_config *config = f->config;

	if (config) {
		usb_put_function(config->func);
		usb_put_function_instance(config->fi);
	}

	kfree(f->config);
	f->config = NULL;
}

static int uac2_function_bind_config(struct android_usb_function *f,
					  struct usb_configuration *c)
{
	struct uac2_function_config *config = f->config;

	return usb_add_function(c, config->func);
}

static struct android_usb_function uac2_function = {
	.name		= "uac2_func",
	.init		= uac2_function_init,
	.cleanup	= uac2_function_cleanup,
	.bind_config	= uac2_function_bind_config,
};

#ifdef CONFIG_MEDIA_SUPPORT
/* PERIPHERAL VIDEO */
struct video_function_config {
@@ -3222,6 +3280,7 @@ static struct android_usb_function *default_functions[] = {
	&ecm_qc_function,
#ifdef CONFIG_SND_PCM
	&audio_function,
	&uac2_function,
#endif
#ifdef CONFIG_MEDIA_SUPPORT
	&video_function,
+50 −1
Original line number Diff line number Diff line
@@ -522,6 +522,7 @@ static int alsa_uac2_init(struct audio_dev *agdev)
	struct snd_uac2_chip *uac2 = &agdev->uac2;
	int err;

	memset(&uac2->pdev, 0, sizeof(uac2->pdev));
	uac2->pdrv.probe = snd_uac2_probe;
	uac2->pdrv.remove = snd_uac2_remove;
	uac2->pdrv.driver.name = uac2_name;
@@ -791,6 +792,13 @@ struct usb_endpoint_descriptor hs_epout_desc = {
	.bInterval = 4,
};

static struct usb_ss_ep_comp_descriptor ss_epout_comp_desc = {
	 .bLength =		 sizeof(ss_epout_comp_desc),
	 .bDescriptorType =	 USB_DT_SS_ENDPOINT_COMP,

	 .wBytesPerInterval =	cpu_to_le16(1024),
};

/* CS AS ISO OUT Endpoint */
static struct uac2_iso_endpoint_descriptor as_iso_out_desc = {
	.bLength = sizeof as_iso_out_desc,
@@ -868,6 +876,13 @@ struct usb_endpoint_descriptor hs_epin_desc = {
	.bInterval = 4,
};

static struct usb_ss_ep_comp_descriptor ss_epin_comp_desc = {
	 .bLength =		 sizeof(ss_epin_comp_desc),
	 .bDescriptorType =	 USB_DT_SS_ENDPOINT_COMP,

	 .wBytesPerInterval =	cpu_to_le16(1024),
};

/* CS AS ISO IN Endpoint */
static struct uac2_iso_endpoint_descriptor as_iso_in_desc = {
	.bLength = sizeof as_iso_in_desc,
@@ -940,6 +955,38 @@ static struct usb_descriptor_header *hs_audio_desc[] = {
	NULL,
};

static struct usb_descriptor_header *ss_audio_desc[] = {
	(struct usb_descriptor_header *)&iad_desc,
	(struct usb_descriptor_header *)&std_ac_if_desc,

	(struct usb_descriptor_header *)&ac_hdr_desc,
	(struct usb_descriptor_header *)&in_clk_src_desc,
	(struct usb_descriptor_header *)&out_clk_src_desc,
	(struct usb_descriptor_header *)&usb_out_it_desc,
	(struct usb_descriptor_header *)&io_in_it_desc,
	(struct usb_descriptor_header *)&usb_in_ot_desc,
	(struct usb_descriptor_header *)&io_out_ot_desc,

	(struct usb_descriptor_header *)&std_as_out_if0_desc,
	(struct usb_descriptor_header *)&std_as_out_if1_desc,

	(struct usb_descriptor_header *)&as_out_hdr_desc,
	(struct usb_descriptor_header *)&as_out_fmt1_desc,
	(struct usb_descriptor_header *)&hs_epout_desc,
	(struct usb_descriptor_header *)&ss_epout_comp_desc,
	(struct usb_descriptor_header *)&as_iso_out_desc,

	(struct usb_descriptor_header *)&std_as_in_if0_desc,
	(struct usb_descriptor_header *)&std_as_in_if1_desc,

	(struct usb_descriptor_header *)&as_in_hdr_desc,
	(struct usb_descriptor_header *)&as_in_fmt1_desc,
	(struct usb_descriptor_header *)&hs_epin_desc,
	(struct usb_descriptor_header *)&ss_epin_comp_desc,
	(struct usb_descriptor_header *)&as_iso_in_desc,
	NULL,
};

struct cntrl_cur_lay3 {
	__u32	dCUR;
};
@@ -1030,6 +1077,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
		return ret;
	}
	std_ac_if_desc.bInterfaceNumber = ret;
	iad_desc.bFirstInterface = ret;
	agdev->ac_intf = ret;
	agdev->ac_alt = 0;

@@ -1075,7 +1123,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
	hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
	hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;

	ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
	ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc,
					 ss_audio_desc);
	if (ret)
		goto err;

+1 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@

#include <linux/usb/composite.h>

#define UAC2_DEF_PCHMASK 0x3
#define UAC2_DEF_PCHMASK 0x1
#define UAC2_DEF_PSRATE 48000
#define UAC2_DEF_PSSIZE 2
#define UAC2_DEF_CCHMASK 0x3