Skip to content

Commit ec644b5

Browse files
Meng Dongyangrkhuangtao
authored andcommitted
usb: gadget: uac: fix error of uac unit and add control unit
Accordding to the "Universal Serial Bus Device Class Definition for Audio Devices", there are some error in the f_audio_source driver. The audio source can't be recognize by the Windows PC if control unit is not support. In order to support Windows PC, this patch fix error in f_audio_source driver and add support of control unit. Change-Id: Ie508141f032adecfbe2e951ad36d9b8c271b28ba Signed-off-by: Meng Dongyang <daniel.meng@rock-chips.com>
1 parent 199b577 commit ec644b5

1 file changed

Lines changed: 179 additions & 19 deletions

File tree

drivers/usb/gadget/function/f_audio_source.c

Lines changed: 179 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,12 @@
4141

4242
#define AUDIO_AC_INTERFACE 0
4343
#define AUDIO_AS_INTERFACE 1
44-
#define AUDIO_NUM_INTERFACES 2
44+
#define AUDIO_NUM_INTERFACES 1
4545
#define MAX_INST_NAME_LEN 40
4646

47+
static int audio_set_cmd(struct usb_audio_control *con, u8 cmd, int value);
48+
static int audio_get_cmd(struct usb_audio_control *con, u8 cmd);
49+
4750
static u32 sample_rate_table[] = {
4851
8000, 11025, 16000, 22050, 24000,
4952
32000, 40000, 44100, 48000, 56000,
@@ -59,24 +62,23 @@ static struct usb_interface_descriptor ac_interface_desc = {
5962
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
6063
};
6164

62-
DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
65+
DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
6366

6467
#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(AUDIO_NUM_INTERFACES)
6568
/* 1 input terminal, 1 output terminal and 1 feature unit */
6669
#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH \
6770
+ UAC_DT_INPUT_TERMINAL_SIZE + UAC_DT_OUTPUT_TERMINAL_SIZE \
6871
+ UAC_DT_FEATURE_UNIT_SIZE(0))
6972
/* B.3.2 Class-Specific AC Interface Descriptor */
70-
static struct uac1_ac_header_descriptor_2 ac_header_desc = {
73+
static struct uac1_ac_header_descriptor_1 ac_header_desc = {
7174
.bLength = UAC_DT_AC_HEADER_LENGTH,
7275
.bDescriptorType = USB_DT_CS_INTERFACE,
7376
.bDescriptorSubtype = UAC_HEADER,
7477
.bcdADC = __constant_cpu_to_le16(0x0100),
7578
.wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH),
7679
.bInCollection = AUDIO_NUM_INTERFACES,
7780
.baInterfaceNr = {
78-
[0] = AUDIO_AC_INTERFACE,
79-
[1] = AUDIO_AS_INTERFACE,
81+
[0] = AUDIO_AS_INTERFACE,
8082
}
8183
};
8284

@@ -88,7 +90,7 @@ static struct uac_input_terminal_descriptor input_terminal_desc = {
8890
.bTerminalID = INPUT_TERMINAL_ID,
8991
.wTerminalType = UAC_INPUT_TERMINAL_MICROPHONE,
9092
.bAssocTerminal = 0,
91-
.wChannelConfig = 0x3,
93+
.wChannelConfig = 0,
9294
};
9395

9496
DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0);
@@ -100,7 +102,34 @@ static struct uac_feature_unit_descriptor_0 feature_unit_desc = {
100102
.bDescriptorSubtype = UAC_FEATURE_UNIT,
101103
.bUnitID = FEATURE_UNIT_ID,
102104
.bSourceID = INPUT_TERMINAL_ID,
103-
.bControlSize = 2,
105+
.bControlSize = 1,
106+
.bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME),
107+
};
108+
109+
static struct usb_audio_control mute_control = {
110+
.list = LIST_HEAD_INIT(mute_control.list),
111+
.name = "Mute Control",
112+
.type = UAC_FU_MUTE,
113+
/* Todo: add real Mute control code */
114+
.set = audio_set_cmd,
115+
.get = audio_get_cmd,
116+
};
117+
118+
static struct usb_audio_control volume_control = {
119+
.list = LIST_HEAD_INIT(volume_control.list),
120+
.name = "Volume Control",
121+
.type = UAC_FU_VOLUME,
122+
/* Todo: add real Volume control code */
123+
.set = audio_set_cmd,
124+
.get = audio_get_cmd,
125+
};
126+
127+
static struct usb_audio_control_selector feature_unit = {
128+
.list = LIST_HEAD_INIT(feature_unit.list),
129+
.id = FEATURE_UNIT_ID,
130+
.name = "Mute & Volume Control",
131+
.type = UAC_FEATURE_UNIT,
132+
.desc = (struct usb_descriptor_header *)&feature_unit_desc,
104133
};
105134

106135
#define OUTPUT_TERMINAL_ID 3
@@ -138,7 +167,7 @@ static struct uac1_as_header_descriptor as_header_desc = {
138167
.bLength = UAC_DT_AS_HEADER_SIZE,
139168
.bDescriptorType = USB_DT_CS_INTERFACE,
140169
.bDescriptorSubtype = UAC_AS_GENERAL,
141-
.bTerminalLink = INPUT_TERMINAL_ID,
170+
.bTerminalLink = OUTPUT_TERMINAL_ID,
142171
.bDelay = 1,
143172
.wFormatTag = UAC_FORMAT_TYPE_I_PCM,
144173
};
@@ -233,8 +262,8 @@ static struct snd_pcm_hardware audio_hw_info = {
233262
SNDRV_PCM_INFO_BLOCK_TRANSFER,
234263

235264
.formats = SNDRV_PCM_FMTBIT_S16_LE,
236-
.channels_min = 2,
237-
.channels_max = 2,
265+
.channels_min = 1,
266+
.channels_max = 1,
238267
.rate_min = MIN_SAMPLE_RATE,
239268
.rate_max = MAX_SAMPLE_RATE,
240269

@@ -278,6 +307,11 @@ struct audio_dev {
278307

279308
unsigned int alt;
280309

310+
/* Control Set command */
311+
u8 set_cmd;
312+
struct list_head cs;
313+
struct usb_audio_control *set_con;
314+
281315
/* byte size of a "period" */
282316
unsigned int period;
283317
/* bytes sent since last call to snd_pcm_period_elapsed */
@@ -437,6 +471,36 @@ static void audio_request_free(struct usb_request *req, struct usb_ep *ep)
437471
}
438472
}
439473

474+
static int audio_set_cmd(struct usb_audio_control *con, u8 cmd, int value)
475+
{
476+
con->data[cmd] = value;
477+
478+
return 0;
479+
}
480+
481+
static int audio_get_cmd(struct usb_audio_control *con, u8 cmd)
482+
{
483+
return con->data[cmd];
484+
}
485+
486+
/* Todo: add more control selecotor dynamically */
487+
static int control_selector_init(struct audio_dev *audio)
488+
{
489+
INIT_LIST_HEAD(&audio->cs);
490+
list_add(&feature_unit.list, &audio->cs);
491+
492+
INIT_LIST_HEAD(&feature_unit.control);
493+
list_add(&mute_control.list, &feature_unit.control);
494+
list_add(&volume_control.list, &feature_unit.control);
495+
496+
volume_control.data[UAC__CUR] = 0xffc0;
497+
volume_control.data[UAC__MIN] = 0xe3a0;
498+
volume_control.data[UAC__MAX] = 0xfff0;
499+
volume_control.data[UAC__RES] = 0x0030;
500+
501+
return 0;
502+
}
503+
440504
static void audio_req_put(struct audio_dev *audio, struct usb_request *req)
441505
{
442506
unsigned long flags;
@@ -544,8 +608,9 @@ static void audio_send(struct audio_dev *audio)
544608

545609
static void audio_control_complete(struct usb_ep *ep, struct usb_request *req)
546610
{
547-
struct audio_dev *audio = ep->driver_data;
611+
struct audio_dev *audio = req->context;
548612
u8 *buf = req->buf;
613+
u32 data = 0;
549614

550615
pr_debug("audio_control_complete req->status %d req->actual %d\n",
551616
req->status, req->actual);
@@ -578,6 +643,12 @@ static void audio_control_complete(struct usb_ep *ep, struct usb_request *req)
578643
break;
579644
}
580645
}
646+
if (audio->set_con) {
647+
memcpy(&data, req->buf, req->length);
648+
audio->set_con->set(audio->set_con, audio->set_cmd,
649+
le16_to_cpu(data));
650+
audio->set_con = NULL;
651+
}
581652
}
582653

583654
static void audio_data_complete(struct usb_ep *ep, struct usb_request *req)
@@ -684,9 +755,78 @@ static int audio_get_endpoint_req(struct usb_function *f,
684755
return value;
685756
}
686757

758+
static int audio_set_intf_req(struct usb_function *f,
759+
const struct usb_ctrlrequest *ctrl)
760+
{
761+
struct audio_dev *audio = func_to_audio(f);
762+
struct usb_composite_dev *cdev = f->config->cdev;
763+
u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
764+
u16 len = le16_to_cpu(ctrl->wLength);
765+
u16 w_value = le16_to_cpu(ctrl->wValue);
766+
u8 con_sel = (w_value >> 8) & 0xFF;
767+
u8 cmd = (ctrl->bRequest & 0x0F);
768+
struct usb_audio_control_selector *cs;
769+
struct usb_audio_control *con;
770+
771+
DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
772+
ctrl->bRequest, w_value, len, id);
773+
774+
list_for_each_entry(cs, &audio->cs, list) {
775+
if (cs->id == id) {
776+
list_for_each_entry(con, &cs->control, list) {
777+
if (con->type == con_sel) {
778+
audio->set_con = con;
779+
break;
780+
}
781+
}
782+
break;
783+
}
784+
}
785+
786+
audio->set_cmd = cmd;
787+
788+
return len;
789+
}
790+
791+
static int audio_get_intf_req(struct usb_function *f,
792+
const struct usb_ctrlrequest *ctrl)
793+
{
794+
struct audio_dev *audio = func_to_audio(f);
795+
struct usb_composite_dev *cdev = f->config->cdev;
796+
struct usb_request *req = cdev->req;
797+
int value = -EOPNOTSUPP;
798+
u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
799+
u16 len = le16_to_cpu(ctrl->wLength);
800+
u16 w_value = le16_to_cpu(ctrl->wValue);
801+
u8 con_sel = (w_value >> 8) & 0xFF;
802+
u8 cmd = (ctrl->bRequest & 0x0F);
803+
struct usb_audio_control_selector *cs;
804+
struct usb_audio_control *con;
805+
806+
DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
807+
ctrl->bRequest, w_value, len, id);
808+
809+
list_for_each_entry(cs, &audio->cs, list) {
810+
if (cs->id == id) {
811+
list_for_each_entry(con, &cs->control, list) {
812+
if (con->type == con_sel && con->get) {
813+
value = con->get(con, cmd);
814+
break;
815+
}
816+
}
817+
}
818+
}
819+
820+
len = min_t(size_t, sizeof(value), len);
821+
memcpy(req->buf, &value, len);
822+
823+
return len;
824+
}
825+
687826
static int
688827
audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
689828
{
829+
struct audio_dev *audio = func_to_audio(f);
690830
struct usb_composite_dev *cdev = f->config->cdev;
691831
struct usb_request *req = cdev->req;
692832
int value = -EOPNOTSUPP;
@@ -705,6 +845,14 @@ audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
705845
case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
706846
value = audio_get_endpoint_req(f, ctrl);
707847
break;
848+
849+
case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
850+
value = audio_set_intf_req(f, ctrl);
851+
break;
852+
853+
case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
854+
value = audio_get_intf_req(f, ctrl);
855+
break;
708856
}
709857

710858
/* respond with data transfer or status phase? */
@@ -715,6 +863,7 @@ audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
715863
req->zero = 0;
716864
req->length = value;
717865
req->complete = audio_control_complete;
866+
req->context = audio;
718867
value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
719868
if (value < 0)
720869
pr_err("audio response on err %d\n", value);
@@ -745,6 +894,15 @@ static int audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
745894
return 0;
746895
}
747896

897+
static int audio_get_alt(struct usb_function *f, unsigned intf)
898+
{
899+
struct audio_dev *audio = func_to_audio(f);
900+
901+
pr_debug("%s intf %d, alt %d\n", __func__, intf, audio->alt);
902+
903+
return audio->alt;
904+
}
905+
748906
static void audio_disable(struct usb_function *f)
749907
{
750908
struct audio_dev *audio = func_to_audio(f);
@@ -766,8 +924,8 @@ static void audio_build_desc(struct audio_dev *audio)
766924
u32 rate, i;
767925

768926
/* Set channel numbers */
769-
input_terminal_desc.bNrChannels = 2;
770-
as_type_i_desc.bNrChannels = 2;
927+
input_terminal_desc.bNrChannels = 1;
928+
as_type_i_desc.bNrChannels = 1;
771929

772930
/* Set sample rates */
773931
for (i = 0; i < ARRAY_SIZE(sample_rate_table); i++) {
@@ -806,6 +964,8 @@ audio_bind(struct usb_configuration *c, struct usb_function *f)
806964
audio->sample_rate = DEFAULT_SAMPLE_RATE;
807965
audio->frames_per_msec = DEFAULT_FRAMES_PER_MSEC;
808966

967+
control_selector_init(audio);
968+
809969
err = snd_card_setup(c, config);
810970
if (err)
811971
return err;
@@ -826,17 +986,14 @@ audio_bind(struct usb_configuration *c, struct usb_function *f)
826986
goto fail;
827987
ac_interface_desc.bInterfaceNumber = status;
828988

829-
/* AUDIO_AC_INTERFACE */
830-
ac_header_desc.baInterfaceNr[0] = status;
831-
832989
status = usb_interface_id(c, f);
833990
if (status < 0)
834991
goto fail;
835992
as_interface_alt_0_desc.bInterfaceNumber = status;
836993
as_interface_alt_1_desc.bInterfaceNumber = status;
837994

838995
/* AUDIO_AS_INTERFACE */
839-
ac_header_desc.baInterfaceNr[1] = status;
996+
ac_header_desc.baInterfaceNr[0] = status;
840997

841998
status = -ENODEV;
842999

@@ -925,7 +1082,7 @@ static int audio_pcm_open(struct snd_pcm_substream *substream)
9251082
runtime->private_data = audio;
9261083
runtime->hw = audio_hw_info;
9271084
snd_pcm_limit_hw_rates(runtime);
928-
runtime->hw.channels_max = 2;
1085+
runtime->hw.channels_max = 1;
9291086

9301087
audio->substream = substream;
9311088

@@ -959,7 +1116,7 @@ static int audio_pcm_hw_params(struct snd_pcm_substream *substream,
9591116

9601117
if (rate > MAX_SAMPLE_RATE || rate < MIN_SAMPLE_RATE)
9611118
return -EINVAL;
962-
if (channels != 2)
1119+
if (channels != 1)
9631120
return -EINVAL;
9641121

9651122
return snd_pcm_lib_alloc_vmalloc_buffer(substream,
@@ -1026,6 +1183,7 @@ static struct audio_dev _audio_dev = {
10261183
.bind = audio_bind,
10271184
.unbind = audio_unbind,
10281185
.set_alt = audio_set_alt,
1186+
.get_alt = audio_get_alt,
10291187
.setup = audio_setup,
10301188
.disable = audio_disable,
10311189
.free_func = audio_free_func,
@@ -1064,6 +1222,8 @@ int audio_source_bind_config(struct usb_configuration *c,
10641222
if (err)
10651223
return err;
10661224

1225+
control_selector_init(audio);
1226+
10671227
err = usb_add_function(c, &audio->func);
10681228
if (err)
10691229
goto add_fail;

0 commit comments

Comments
 (0)