summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjay Agarwal <ajaya@codeaurora.org>2018-11-27 19:48:19 +0530
committerAjay Agarwal <ajaya@codeaurora.org>2019-01-09 10:17:01 +0530
commit7b33db7c8ef9de51e72c3e40156654a941cc1489 (patch)
tree13b334ba36daa370ea5b2f92543b23c6cdd0d96b
parent250bb0182b12f78a299c28873baba0a0828c0a29 (diff)
usb: gadget: f_uac1: Add support for UAC1 function
Add support for the UAC1 function with the configfs framework along with following other changes: - Add dynamic updation of AudioStreaming interface numbers in the AudioControl interface descriptor. - Add superspeed support. - Stop playback on func disable so that pending request's completion is called before request has been freed in unbind. - Fix minor compilation issue. Change-Id: Ib30fa735314c57b9543f89e18d1fb419ed5a2b9d Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
-rw-r--r--drivers/usb/gadget/function/f_uac1.c70
1 files changed, 63 insertions, 7 deletions
diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
index 29efbedc91f9..0445b2e1d8b5 100644
--- a/drivers/usb/gadget/function/f_uac1.c
+++ b/drivers/usb/gadget/function/f_uac1.c
@@ -79,11 +79,6 @@ static struct uac1_ac_header_descriptor_2 ac_header_desc = {
.bcdADC = cpu_to_le16(0x0100),
.wTotalLength = cpu_to_le16(UAC_DT_TOTAL_LENGTH),
.bInCollection = F_AUDIO_NUM_INTERFACES,
- .baInterfaceNr = {
- /* Interface number of the AudioStream interfaces */
- [0] = 1,
- [1] = 2,
- }
};
#define USB_OUT_IT_ID 1
@@ -209,6 +204,13 @@ static struct usb_endpoint_descriptor as_out_ep_desc = {
.bInterval = 4,
};
+static struct usb_ss_ep_comp_descriptor as_out_ep_comp_desc = {
+ .bLength = sizeof(as_out_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ .wBytesPerInterval = cpu_to_le16(1024),
+};
+
/* Class-specific AS ISO OUT Endpoint Descriptor */
static struct uac_iso_endpoint_descriptor as_iso_out_desc = {
.bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
@@ -240,6 +242,13 @@ static struct usb_endpoint_descriptor as_in_ep_desc = {
.bInterval = 4,
};
+static struct usb_ss_ep_comp_descriptor as_in_ep_comp_desc = {
+ .bLength = sizeof(as_in_ep_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ .wBytesPerInterval = cpu_to_le16(1024),
+};
+
/* Class-specific AS ISO OUT Endpoint Descriptor */
static struct uac_iso_endpoint_descriptor as_iso_in_desc = {
.bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
@@ -279,6 +288,37 @@ static struct usb_descriptor_header *f_audio_desc[] = {
NULL,
};
+static struct usb_descriptor_header *f_audio_ss_desc[] = {
+ (struct usb_descriptor_header *)&ac_interface_desc,
+ (struct usb_descriptor_header *)&ac_header_desc,
+
+ (struct usb_descriptor_header *)&usb_out_it_desc,
+ (struct usb_descriptor_header *)&io_out_ot_desc,
+ (struct usb_descriptor_header *)&io_in_it_desc,
+ (struct usb_descriptor_header *)&usb_in_ot_desc,
+
+ (struct usb_descriptor_header *)&as_out_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_out_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_out_header_desc,
+
+ (struct usb_descriptor_header *)&as_out_type_i_desc,
+
+ (struct usb_descriptor_header *)&as_out_ep_desc,
+ (struct usb_descriptor_header *)&as_out_ep_comp_desc,
+ (struct usb_descriptor_header *)&as_iso_out_desc,
+
+ (struct usb_descriptor_header *)&as_in_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_in_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_in_header_desc,
+
+ (struct usb_descriptor_header *)&as_in_type_i_desc,
+
+ (struct usb_descriptor_header *)&as_in_ep_desc,
+ (struct usb_descriptor_header *)&as_in_ep_comp_desc,
+ (struct usb_descriptor_header *)&as_iso_in_desc,
+ NULL,
+};
+
enum {
STR_AC_IF,
STR_USB_OUT_IT,
@@ -504,6 +544,7 @@ static void f_audio_disable(struct usb_function *f)
uac1->as_in_alt = 0;
u_audio_stop_capture(&uac1->g_audio);
+ u_audio_stop_playback(&uac1->g_audio);
}
/*-------------------------------------------------------------------------*/
@@ -570,6 +611,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
+ ac_header_desc.baInterfaceNr[0] = status;
as_out_interface_alt_0_desc.bInterfaceNumber = status;
as_out_interface_alt_1_desc.bInterfaceNumber = status;
uac1->as_out_intf = status;
@@ -578,6 +620,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
+ ac_header_desc.baInterfaceNr[1] = status;
as_in_interface_alt_0_desc.bInterfaceNumber = status;
as_in_interface_alt_1_desc.bInterfaceNumber = status;
uac1->as_in_intf = status;
@@ -601,8 +644,8 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
audio->in_ep->desc = &as_in_ep_desc;
/* copy descriptors, and track endpoint copies */
- status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL,
- NULL);
+ status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc,
+ f_audio_ss_desc);
if (status)
goto fail;
@@ -798,5 +841,18 @@ static struct usb_function *f_audio_alloc(struct usb_function_instance *fi)
}
DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc);
+
+static int __init afunc_init(void)
+{
+ return usb_function_register(&uac1usb_func);
+}
+
+static void __exit afunc_exit(void)
+{
+ usb_function_unregister(&uac1usb_func);
+}
+
+module_init(afunc_init);
+module_exit(afunc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ruslan Bilovol");