1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * f_uac2.c -- USB Audio Class 2.0 Function |
4 | * |
5 | * Copyright (C) 2011 |
6 | * Yadwinder Singh (yadi.brar01@gmail.com) |
7 | * Jaswinder Singh (jaswinder.singh@linaro.org) |
8 | * |
9 | * Copyright (C) 2020 |
10 | * Ruslan Bilovol (ruslan.bilovol@gmail.com) |
11 | */ |
12 | |
13 | #include <linux/usb/audio.h> |
14 | #include <linux/usb/audio-v2.h> |
15 | #include <linux/module.h> |
16 | |
17 | #include "u_audio.h" |
18 | |
19 | #include "u_uac2.h" |
20 | |
21 | /* UAC2 spec: 4.1 Audio Channel Cluster Descriptor */ |
22 | #define UAC2_CHANNEL_MASK 0x07FFFFFF |
23 | |
24 | /* |
25 | * The driver implements a simple UAC_2 topology. |
26 | * USB-OUT -> IT_1 -> FU -> OT_3 -> ALSA_Capture |
27 | * ALSA_Playback -> IT_2 -> FU -> OT_4 -> USB-IN |
28 | * Capture and Playback sampling rates are independently |
29 | * controlled by two clock sources : |
30 | * CLK_5 := c_srate, and CLK_6 := p_srate |
31 | */ |
32 | #define USB_OUT_CLK_ID (out_clk_src_desc.bClockID) |
33 | #define USB_IN_CLK_ID (in_clk_src_desc.bClockID) |
34 | #define USB_OUT_FU_ID (out_feature_unit_desc->bUnitID) |
35 | #define USB_IN_FU_ID (in_feature_unit_desc->bUnitID) |
36 | |
37 | #define CONTROL_ABSENT 0 |
38 | #define CONTROL_RDONLY 1 |
39 | #define CONTROL_RDWR 3 |
40 | |
41 | #define CLK_FREQ_CTRL 0 |
42 | #define CLK_VLD_CTRL 2 |
43 | #define FU_MUTE_CTRL 0 |
44 | #define FU_VOL_CTRL 2 |
45 | |
46 | #define COPY_CTRL 0 |
47 | #define CONN_CTRL 2 |
48 | #define OVRLD_CTRL 4 |
49 | #define CLSTR_CTRL 6 |
50 | #define UNFLW_CTRL 8 |
51 | #define OVFLW_CTRL 10 |
52 | |
53 | #define EPIN_EN(_opts) ((_opts)->p_chmask != 0) |
54 | #define EPOUT_EN(_opts) ((_opts)->c_chmask != 0) |
55 | #define FUIN_EN(_opts) (EPIN_EN(_opts) \ |
56 | && ((_opts)->p_mute_present \ |
57 | || (_opts)->p_volume_present)) |
58 | #define FUOUT_EN(_opts) (EPOUT_EN(_opts) \ |
59 | && ((_opts)->c_mute_present \ |
60 | || (_opts)->c_volume_present)) |
61 | #define EPOUT_FBACK_IN_EN(_opts) ((_opts)->c_sync == USB_ENDPOINT_SYNC_ASYNC) |
62 | |
63 | struct f_uac2 { |
64 | struct g_audio g_audio; |
65 | u8 ac_intf, as_in_intf, as_out_intf; |
66 | u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */ |
67 | |
68 | struct usb_ctrlrequest setup_cr; /* will be used in data stage */ |
69 | |
70 | /* Interrupt IN endpoint of AC interface */ |
71 | struct usb_ep *int_ep; |
72 | atomic_t int_count; |
73 | /* transient state, only valid during handling of a single control request */ |
74 | int clock_id; |
75 | }; |
76 | |
77 | static inline struct f_uac2 *func_to_uac2(struct usb_function *f) |
78 | { |
79 | return container_of(f, struct f_uac2, g_audio.func); |
80 | } |
81 | |
82 | static inline |
83 | struct f_uac2_opts *g_audio_to_uac2_opts(struct g_audio *agdev) |
84 | { |
85 | return container_of(agdev->func.fi, struct f_uac2_opts, func_inst); |
86 | } |
87 | |
88 | static int afunc_notify(struct g_audio *agdev, int unit_id, int cs); |
89 | |
90 | /* --------- USB Function Interface ------------- */ |
91 | |
92 | enum { |
93 | STR_ASSOC, |
94 | STR_IF_CTRL, |
95 | STR_CLKSRC_IN, |
96 | STR_CLKSRC_OUT, |
97 | STR_USB_IT, |
98 | STR_IO_IT, |
99 | STR_USB_OT, |
100 | STR_IO_OT, |
101 | STR_FU_IN, |
102 | STR_FU_OUT, |
103 | STR_AS_OUT_ALT0, |
104 | STR_AS_OUT_ALT1, |
105 | STR_AS_IN_ALT0, |
106 | STR_AS_IN_ALT1, |
107 | }; |
108 | |
109 | static struct usb_string strings_fn[] = { |
110 | /* [STR_ASSOC].s = DYNAMIC, */ |
111 | [STR_IF_CTRL].s = "Topology Control" , |
112 | [STR_CLKSRC_IN].s = "Input Clock" , |
113 | [STR_CLKSRC_OUT].s = "Output Clock" , |
114 | [STR_USB_IT].s = "USBH Out" , |
115 | [STR_IO_IT].s = "USBD Out" , |
116 | [STR_USB_OT].s = "USBH In" , |
117 | [STR_IO_OT].s = "USBD In" , |
118 | [STR_FU_IN].s = "Capture Volume" , |
119 | [STR_FU_OUT].s = "Playback Volume" , |
120 | [STR_AS_OUT_ALT0].s = "Playback Inactive" , |
121 | [STR_AS_OUT_ALT1].s = "Playback Active" , |
122 | [STR_AS_IN_ALT0].s = "Capture Inactive" , |
123 | [STR_AS_IN_ALT1].s = "Capture Active" , |
124 | { }, |
125 | }; |
126 | |
127 | static const char *const speed_names[] = { |
128 | [USB_SPEED_UNKNOWN] = "UNKNOWN" , |
129 | [USB_SPEED_LOW] = "LS" , |
130 | [USB_SPEED_FULL] = "FS" , |
131 | [USB_SPEED_HIGH] = "HS" , |
132 | [USB_SPEED_WIRELESS] = "W" , |
133 | [USB_SPEED_SUPER] = "SS" , |
134 | [USB_SPEED_SUPER_PLUS] = "SS+" , |
135 | }; |
136 | |
137 | static struct usb_gadget_strings str_fn = { |
138 | .language = 0x0409, /* en-us */ |
139 | .strings = strings_fn, |
140 | }; |
141 | |
142 | static struct usb_gadget_strings *fn_strings[] = { |
143 | &str_fn, |
144 | NULL, |
145 | }; |
146 | |
147 | static struct usb_interface_assoc_descriptor iad_desc = { |
148 | .bLength = sizeof iad_desc, |
149 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
150 | |
151 | .bFirstInterface = 0, |
152 | .bInterfaceCount = 3, |
153 | .bFunctionClass = USB_CLASS_AUDIO, |
154 | .bFunctionSubClass = UAC2_FUNCTION_SUBCLASS_UNDEFINED, |
155 | .bFunctionProtocol = UAC_VERSION_2, |
156 | }; |
157 | |
158 | /* Audio Control Interface */ |
159 | static struct usb_interface_descriptor std_ac_if_desc = { |
160 | .bLength = sizeof std_ac_if_desc, |
161 | .bDescriptorType = USB_DT_INTERFACE, |
162 | |
163 | .bAlternateSetting = 0, |
164 | /* .bNumEndpoints = DYNAMIC */ |
165 | .bInterfaceClass = USB_CLASS_AUDIO, |
166 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, |
167 | .bInterfaceProtocol = UAC_VERSION_2, |
168 | }; |
169 | |
170 | /* Clock source for IN traffic */ |
171 | static struct uac_clock_source_descriptor in_clk_src_desc = { |
172 | .bLength = sizeof in_clk_src_desc, |
173 | .bDescriptorType = USB_DT_CS_INTERFACE, |
174 | |
175 | .bDescriptorSubtype = UAC2_CLOCK_SOURCE, |
176 | /* .bClockID = DYNAMIC */ |
177 | .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, |
178 | .bmControls = (CONTROL_RDWR << CLK_FREQ_CTRL), |
179 | .bAssocTerminal = 0, |
180 | }; |
181 | |
182 | /* Clock source for OUT traffic */ |
183 | static struct uac_clock_source_descriptor out_clk_src_desc = { |
184 | .bLength = sizeof out_clk_src_desc, |
185 | .bDescriptorType = USB_DT_CS_INTERFACE, |
186 | |
187 | .bDescriptorSubtype = UAC2_CLOCK_SOURCE, |
188 | /* .bClockID = DYNAMIC */ |
189 | .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, |
190 | .bmControls = (CONTROL_RDWR << CLK_FREQ_CTRL), |
191 | .bAssocTerminal = 0, |
192 | }; |
193 | |
194 | /* Input Terminal for USB_OUT */ |
195 | static struct uac2_input_terminal_descriptor usb_out_it_desc = { |
196 | .bLength = sizeof usb_out_it_desc, |
197 | .bDescriptorType = USB_DT_CS_INTERFACE, |
198 | |
199 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, |
200 | /* .bTerminalID = DYNAMIC */ |
201 | .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), |
202 | .bAssocTerminal = 0, |
203 | /* .bCSourceID = DYNAMIC */ |
204 | .iChannelNames = 0, |
205 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), |
206 | }; |
207 | |
208 | /* Input Terminal for I/O-In */ |
209 | static struct uac2_input_terminal_descriptor io_in_it_desc = { |
210 | .bLength = sizeof io_in_it_desc, |
211 | .bDescriptorType = USB_DT_CS_INTERFACE, |
212 | |
213 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, |
214 | /* .bTerminalID = DYNAMIC */ |
215 | /* .wTerminalType = DYNAMIC */ |
216 | .bAssocTerminal = 0, |
217 | /* .bCSourceID = DYNAMIC */ |
218 | .iChannelNames = 0, |
219 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), |
220 | }; |
221 | |
222 | /* Ouput Terminal for USB_IN */ |
223 | static struct uac2_output_terminal_descriptor usb_in_ot_desc = { |
224 | .bLength = sizeof usb_in_ot_desc, |
225 | .bDescriptorType = USB_DT_CS_INTERFACE, |
226 | |
227 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, |
228 | /* .bTerminalID = DYNAMIC */ |
229 | .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), |
230 | .bAssocTerminal = 0, |
231 | /* .bSourceID = DYNAMIC */ |
232 | /* .bCSourceID = DYNAMIC */ |
233 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), |
234 | }; |
235 | |
236 | /* Ouput Terminal for I/O-Out */ |
237 | static struct uac2_output_terminal_descriptor io_out_ot_desc = { |
238 | .bLength = sizeof io_out_ot_desc, |
239 | .bDescriptorType = USB_DT_CS_INTERFACE, |
240 | |
241 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, |
242 | /* .bTerminalID = DYNAMIC */ |
243 | /* .wTerminalType = DYNAMIC */ |
244 | .bAssocTerminal = 0, |
245 | /* .bSourceID = DYNAMIC */ |
246 | /* .bCSourceID = DYNAMIC */ |
247 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), |
248 | }; |
249 | |
250 | static struct uac2_feature_unit_descriptor *in_feature_unit_desc; |
251 | static struct uac2_feature_unit_descriptor *out_feature_unit_desc; |
252 | |
253 | static struct uac2_ac_header_descriptor ac_hdr_desc = { |
254 | .bLength = sizeof ac_hdr_desc, |
255 | .bDescriptorType = USB_DT_CS_INTERFACE, |
256 | |
257 | .bDescriptorSubtype = UAC_MS_HEADER, |
258 | .bcdADC = cpu_to_le16(0x200), |
259 | .bCategory = UAC2_FUNCTION_IO_BOX, |
260 | /* .wTotalLength = DYNAMIC */ |
261 | .bmControls = 0, |
262 | }; |
263 | |
264 | /* AC IN Interrupt Endpoint */ |
265 | static struct usb_endpoint_descriptor fs_ep_int_desc = { |
266 | .bLength = USB_DT_ENDPOINT_SIZE, |
267 | .bDescriptorType = USB_DT_ENDPOINT, |
268 | |
269 | .bEndpointAddress = USB_DIR_IN, |
270 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
271 | .wMaxPacketSize = cpu_to_le16(6), |
272 | .bInterval = 1, |
273 | }; |
274 | |
275 | static struct usb_endpoint_descriptor hs_ep_int_desc = { |
276 | .bLength = USB_DT_ENDPOINT_SIZE, |
277 | .bDescriptorType = USB_DT_ENDPOINT, |
278 | |
279 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
280 | .wMaxPacketSize = cpu_to_le16(6), |
281 | .bInterval = 4, |
282 | }; |
283 | |
284 | static struct usb_endpoint_descriptor ss_ep_int_desc = { |
285 | .bLength = USB_DT_ENDPOINT_SIZE, |
286 | .bDescriptorType = USB_DT_ENDPOINT, |
287 | |
288 | .bEndpointAddress = USB_DIR_IN, |
289 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
290 | .wMaxPacketSize = cpu_to_le16(6), |
291 | .bInterval = 4, |
292 | }; |
293 | |
294 | static struct usb_ss_ep_comp_descriptor ss_ep_int_desc_comp = { |
295 | .bLength = sizeof(ss_ep_int_desc_comp), |
296 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
297 | .wBytesPerInterval = cpu_to_le16(6), |
298 | }; |
299 | |
300 | /* Audio Streaming OUT Interface - Alt0 */ |
301 | static struct usb_interface_descriptor std_as_out_if0_desc = { |
302 | .bLength = sizeof std_as_out_if0_desc, |
303 | .bDescriptorType = USB_DT_INTERFACE, |
304 | |
305 | .bAlternateSetting = 0, |
306 | .bNumEndpoints = 0, |
307 | .bInterfaceClass = USB_CLASS_AUDIO, |
308 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, |
309 | .bInterfaceProtocol = UAC_VERSION_2, |
310 | }; |
311 | |
312 | /* Audio Streaming OUT Interface - Alt1 */ |
313 | static struct usb_interface_descriptor std_as_out_if1_desc = { |
314 | .bLength = sizeof std_as_out_if1_desc, |
315 | .bDescriptorType = USB_DT_INTERFACE, |
316 | |
317 | .bAlternateSetting = 1, |
318 | .bNumEndpoints = 1, |
319 | .bInterfaceClass = USB_CLASS_AUDIO, |
320 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, |
321 | .bInterfaceProtocol = UAC_VERSION_2, |
322 | }; |
323 | |
324 | /* Audio Stream OUT Intface Desc */ |
325 | static struct uac2_as_header_descriptor as_out_hdr_desc = { |
326 | .bLength = sizeof as_out_hdr_desc, |
327 | .bDescriptorType = USB_DT_CS_INTERFACE, |
328 | |
329 | .bDescriptorSubtype = UAC_AS_GENERAL, |
330 | /* .bTerminalLink = DYNAMIC */ |
331 | .bmControls = 0, |
332 | .bFormatType = UAC_FORMAT_TYPE_I, |
333 | .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), |
334 | .iChannelNames = 0, |
335 | }; |
336 | |
337 | /* Audio USB_OUT Format */ |
338 | static struct uac2_format_type_i_descriptor as_out_fmt1_desc = { |
339 | .bLength = sizeof as_out_fmt1_desc, |
340 | .bDescriptorType = USB_DT_CS_INTERFACE, |
341 | .bDescriptorSubtype = UAC_FORMAT_TYPE, |
342 | .bFormatType = UAC_FORMAT_TYPE_I, |
343 | }; |
344 | |
345 | /* STD AS ISO OUT Endpoint */ |
346 | static struct usb_endpoint_descriptor fs_epout_desc = { |
347 | .bLength = USB_DT_ENDPOINT_SIZE, |
348 | .bDescriptorType = USB_DT_ENDPOINT, |
349 | |
350 | .bEndpointAddress = USB_DIR_OUT, |
351 | /* .bmAttributes = DYNAMIC */ |
352 | /* .wMaxPacketSize = DYNAMIC */ |
353 | .bInterval = 1, |
354 | }; |
355 | |
356 | static struct usb_endpoint_descriptor hs_epout_desc = { |
357 | .bLength = USB_DT_ENDPOINT_SIZE, |
358 | .bDescriptorType = USB_DT_ENDPOINT, |
359 | |
360 | /* .bmAttributes = DYNAMIC */ |
361 | /* .wMaxPacketSize = DYNAMIC */ |
362 | /* .bInterval = DYNAMIC */ |
363 | }; |
364 | |
365 | static struct usb_endpoint_descriptor ss_epout_desc = { |
366 | .bLength = USB_DT_ENDPOINT_SIZE, |
367 | .bDescriptorType = USB_DT_ENDPOINT, |
368 | |
369 | .bEndpointAddress = USB_DIR_OUT, |
370 | /* .bmAttributes = DYNAMIC */ |
371 | /* .wMaxPacketSize = DYNAMIC */ |
372 | /* .bInterval = DYNAMIC */ |
373 | }; |
374 | |
375 | static struct usb_ss_ep_comp_descriptor ss_epout_desc_comp = { |
376 | .bLength = sizeof(ss_epout_desc_comp), |
377 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
378 | .bMaxBurst = 0, |
379 | .bmAttributes = 0, |
380 | /* wBytesPerInterval = DYNAMIC */ |
381 | }; |
382 | |
383 | /* CS AS ISO OUT Endpoint */ |
384 | static struct uac2_iso_endpoint_descriptor as_iso_out_desc = { |
385 | .bLength = sizeof as_iso_out_desc, |
386 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
387 | |
388 | .bDescriptorSubtype = UAC_EP_GENERAL, |
389 | .bmAttributes = 0, |
390 | .bmControls = 0, |
391 | .bLockDelayUnits = 0, |
392 | .wLockDelay = 0, |
393 | }; |
394 | |
395 | /* STD AS ISO IN Feedback Endpoint */ |
396 | static struct usb_endpoint_descriptor fs_epin_fback_desc = { |
397 | .bLength = USB_DT_ENDPOINT_SIZE, |
398 | .bDescriptorType = USB_DT_ENDPOINT, |
399 | |
400 | .bEndpointAddress = USB_DIR_IN, |
401 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_USAGE_FEEDBACK, |
402 | .wMaxPacketSize = cpu_to_le16(3), |
403 | .bInterval = 1, |
404 | }; |
405 | |
406 | static struct usb_endpoint_descriptor hs_epin_fback_desc = { |
407 | .bLength = USB_DT_ENDPOINT_SIZE, |
408 | .bDescriptorType = USB_DT_ENDPOINT, |
409 | |
410 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_USAGE_FEEDBACK, |
411 | .wMaxPacketSize = cpu_to_le16(4), |
412 | .bInterval = 4, |
413 | }; |
414 | |
415 | static struct usb_endpoint_descriptor ss_epin_fback_desc = { |
416 | .bLength = USB_DT_ENDPOINT_SIZE, |
417 | .bDescriptorType = USB_DT_ENDPOINT, |
418 | |
419 | .bEndpointAddress = USB_DIR_IN, |
420 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_USAGE_FEEDBACK, |
421 | .wMaxPacketSize = cpu_to_le16(4), |
422 | .bInterval = 4, |
423 | }; |
424 | |
425 | static struct usb_ss_ep_comp_descriptor ss_epin_fback_desc_comp = { |
426 | .bLength = sizeof(ss_epin_fback_desc_comp), |
427 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
428 | .bMaxBurst = 0, |
429 | .bmAttributes = 0, |
430 | .wBytesPerInterval = cpu_to_le16(4), |
431 | }; |
432 | |
433 | |
434 | /* Audio Streaming IN Interface - Alt0 */ |
435 | static struct usb_interface_descriptor std_as_in_if0_desc = { |
436 | .bLength = sizeof std_as_in_if0_desc, |
437 | .bDescriptorType = USB_DT_INTERFACE, |
438 | |
439 | .bAlternateSetting = 0, |
440 | .bNumEndpoints = 0, |
441 | .bInterfaceClass = USB_CLASS_AUDIO, |
442 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, |
443 | .bInterfaceProtocol = UAC_VERSION_2, |
444 | }; |
445 | |
446 | /* Audio Streaming IN Interface - Alt1 */ |
447 | static struct usb_interface_descriptor std_as_in_if1_desc = { |
448 | .bLength = sizeof std_as_in_if1_desc, |
449 | .bDescriptorType = USB_DT_INTERFACE, |
450 | |
451 | .bAlternateSetting = 1, |
452 | .bNumEndpoints = 1, |
453 | .bInterfaceClass = USB_CLASS_AUDIO, |
454 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, |
455 | .bInterfaceProtocol = UAC_VERSION_2, |
456 | }; |
457 | |
458 | /* Audio Stream IN Intface Desc */ |
459 | static struct uac2_as_header_descriptor as_in_hdr_desc = { |
460 | .bLength = sizeof as_in_hdr_desc, |
461 | .bDescriptorType = USB_DT_CS_INTERFACE, |
462 | |
463 | .bDescriptorSubtype = UAC_AS_GENERAL, |
464 | /* .bTerminalLink = DYNAMIC */ |
465 | .bmControls = 0, |
466 | .bFormatType = UAC_FORMAT_TYPE_I, |
467 | .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), |
468 | .iChannelNames = 0, |
469 | }; |
470 | |
471 | /* Audio USB_IN Format */ |
472 | static struct uac2_format_type_i_descriptor as_in_fmt1_desc = { |
473 | .bLength = sizeof as_in_fmt1_desc, |
474 | .bDescriptorType = USB_DT_CS_INTERFACE, |
475 | .bDescriptorSubtype = UAC_FORMAT_TYPE, |
476 | .bFormatType = UAC_FORMAT_TYPE_I, |
477 | }; |
478 | |
479 | /* STD AS ISO IN Endpoint */ |
480 | static struct usb_endpoint_descriptor fs_epin_desc = { |
481 | .bLength = USB_DT_ENDPOINT_SIZE, |
482 | .bDescriptorType = USB_DT_ENDPOINT, |
483 | |
484 | .bEndpointAddress = USB_DIR_IN, |
485 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, |
486 | /* .wMaxPacketSize = DYNAMIC */ |
487 | .bInterval = 1, |
488 | }; |
489 | |
490 | static struct usb_endpoint_descriptor hs_epin_desc = { |
491 | .bLength = USB_DT_ENDPOINT_SIZE, |
492 | .bDescriptorType = USB_DT_ENDPOINT, |
493 | |
494 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, |
495 | /* .wMaxPacketSize = DYNAMIC */ |
496 | /* .bInterval = DYNAMIC */ |
497 | }; |
498 | |
499 | static struct usb_endpoint_descriptor ss_epin_desc = { |
500 | .bLength = USB_DT_ENDPOINT_SIZE, |
501 | .bDescriptorType = USB_DT_ENDPOINT, |
502 | |
503 | .bEndpointAddress = USB_DIR_IN, |
504 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, |
505 | /* .wMaxPacketSize = DYNAMIC */ |
506 | /* .bInterval = DYNAMIC */ |
507 | }; |
508 | |
509 | static struct usb_ss_ep_comp_descriptor ss_epin_desc_comp = { |
510 | .bLength = sizeof(ss_epin_desc_comp), |
511 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
512 | .bMaxBurst = 0, |
513 | .bmAttributes = 0, |
514 | /* wBytesPerInterval = DYNAMIC */ |
515 | }; |
516 | |
517 | /* CS AS ISO IN Endpoint */ |
518 | static struct uac2_iso_endpoint_descriptor as_iso_in_desc = { |
519 | .bLength = sizeof as_iso_in_desc, |
520 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
521 | |
522 | .bDescriptorSubtype = UAC_EP_GENERAL, |
523 | .bmAttributes = 0, |
524 | .bmControls = 0, |
525 | .bLockDelayUnits = 0, |
526 | .wLockDelay = 0, |
527 | }; |
528 | |
529 | static struct usb_descriptor_header *fs_audio_desc[] = { |
530 | (struct usb_descriptor_header *)&iad_desc, |
531 | (struct usb_descriptor_header *)&std_ac_if_desc, |
532 | |
533 | (struct usb_descriptor_header *)&ac_hdr_desc, |
534 | (struct usb_descriptor_header *)&in_clk_src_desc, |
535 | (struct usb_descriptor_header *)&out_clk_src_desc, |
536 | (struct usb_descriptor_header *)&usb_out_it_desc, |
537 | (struct usb_descriptor_header *)&out_feature_unit_desc, |
538 | (struct usb_descriptor_header *)&io_in_it_desc, |
539 | (struct usb_descriptor_header *)&usb_in_ot_desc, |
540 | (struct usb_descriptor_header *)&in_feature_unit_desc, |
541 | (struct usb_descriptor_header *)&io_out_ot_desc, |
542 | |
543 | (struct usb_descriptor_header *)&fs_ep_int_desc, |
544 | |
545 | (struct usb_descriptor_header *)&std_as_out_if0_desc, |
546 | (struct usb_descriptor_header *)&std_as_out_if1_desc, |
547 | |
548 | (struct usb_descriptor_header *)&as_out_hdr_desc, |
549 | (struct usb_descriptor_header *)&as_out_fmt1_desc, |
550 | (struct usb_descriptor_header *)&fs_epout_desc, |
551 | (struct usb_descriptor_header *)&as_iso_out_desc, |
552 | (struct usb_descriptor_header *)&fs_epin_fback_desc, |
553 | |
554 | (struct usb_descriptor_header *)&std_as_in_if0_desc, |
555 | (struct usb_descriptor_header *)&std_as_in_if1_desc, |
556 | |
557 | (struct usb_descriptor_header *)&as_in_hdr_desc, |
558 | (struct usb_descriptor_header *)&as_in_fmt1_desc, |
559 | (struct usb_descriptor_header *)&fs_epin_desc, |
560 | (struct usb_descriptor_header *)&as_iso_in_desc, |
561 | NULL, |
562 | }; |
563 | |
564 | static struct usb_descriptor_header *hs_audio_desc[] = { |
565 | (struct usb_descriptor_header *)&iad_desc, |
566 | (struct usb_descriptor_header *)&std_ac_if_desc, |
567 | |
568 | (struct usb_descriptor_header *)&ac_hdr_desc, |
569 | (struct usb_descriptor_header *)&in_clk_src_desc, |
570 | (struct usb_descriptor_header *)&out_clk_src_desc, |
571 | (struct usb_descriptor_header *)&usb_out_it_desc, |
572 | (struct usb_descriptor_header *)&out_feature_unit_desc, |
573 | (struct usb_descriptor_header *)&io_in_it_desc, |
574 | (struct usb_descriptor_header *)&usb_in_ot_desc, |
575 | (struct usb_descriptor_header *)&in_feature_unit_desc, |
576 | (struct usb_descriptor_header *)&io_out_ot_desc, |
577 | |
578 | (struct usb_descriptor_header *)&hs_ep_int_desc, |
579 | |
580 | (struct usb_descriptor_header *)&std_as_out_if0_desc, |
581 | (struct usb_descriptor_header *)&std_as_out_if1_desc, |
582 | |
583 | (struct usb_descriptor_header *)&as_out_hdr_desc, |
584 | (struct usb_descriptor_header *)&as_out_fmt1_desc, |
585 | (struct usb_descriptor_header *)&hs_epout_desc, |
586 | (struct usb_descriptor_header *)&as_iso_out_desc, |
587 | (struct usb_descriptor_header *)&hs_epin_fback_desc, |
588 | |
589 | (struct usb_descriptor_header *)&std_as_in_if0_desc, |
590 | (struct usb_descriptor_header *)&std_as_in_if1_desc, |
591 | |
592 | (struct usb_descriptor_header *)&as_in_hdr_desc, |
593 | (struct usb_descriptor_header *)&as_in_fmt1_desc, |
594 | (struct usb_descriptor_header *)&hs_epin_desc, |
595 | (struct usb_descriptor_header *)&as_iso_in_desc, |
596 | NULL, |
597 | }; |
598 | |
599 | static struct usb_descriptor_header *ss_audio_desc[] = { |
600 | (struct usb_descriptor_header *)&iad_desc, |
601 | (struct usb_descriptor_header *)&std_ac_if_desc, |
602 | |
603 | (struct usb_descriptor_header *)&ac_hdr_desc, |
604 | (struct usb_descriptor_header *)&in_clk_src_desc, |
605 | (struct usb_descriptor_header *)&out_clk_src_desc, |
606 | (struct usb_descriptor_header *)&usb_out_it_desc, |
607 | (struct usb_descriptor_header *)&out_feature_unit_desc, |
608 | (struct usb_descriptor_header *)&io_in_it_desc, |
609 | (struct usb_descriptor_header *)&usb_in_ot_desc, |
610 | (struct usb_descriptor_header *)&in_feature_unit_desc, |
611 | (struct usb_descriptor_header *)&io_out_ot_desc, |
612 | |
613 | (struct usb_descriptor_header *)&ss_ep_int_desc, |
614 | (struct usb_descriptor_header *)&ss_ep_int_desc_comp, |
615 | |
616 | (struct usb_descriptor_header *)&std_as_out_if0_desc, |
617 | (struct usb_descriptor_header *)&std_as_out_if1_desc, |
618 | |
619 | (struct usb_descriptor_header *)&as_out_hdr_desc, |
620 | (struct usb_descriptor_header *)&as_out_fmt1_desc, |
621 | (struct usb_descriptor_header *)&ss_epout_desc, |
622 | (struct usb_descriptor_header *)&ss_epout_desc_comp, |
623 | (struct usb_descriptor_header *)&as_iso_out_desc, |
624 | (struct usb_descriptor_header *)&ss_epin_fback_desc, |
625 | (struct usb_descriptor_header *)&ss_epin_fback_desc_comp, |
626 | |
627 | (struct usb_descriptor_header *)&std_as_in_if0_desc, |
628 | (struct usb_descriptor_header *)&std_as_in_if1_desc, |
629 | |
630 | (struct usb_descriptor_header *)&as_in_hdr_desc, |
631 | (struct usb_descriptor_header *)&as_in_fmt1_desc, |
632 | (struct usb_descriptor_header *)&ss_epin_desc, |
633 | (struct usb_descriptor_header *)&ss_epin_desc_comp, |
634 | (struct usb_descriptor_header *)&as_iso_in_desc, |
635 | NULL, |
636 | }; |
637 | |
638 | struct cntrl_cur_lay2 { |
639 | __le16 wCUR; |
640 | }; |
641 | |
642 | struct cntrl_range_lay2 { |
643 | __le16 wNumSubRanges; |
644 | __le16 wMIN; |
645 | __le16 wMAX; |
646 | __le16 wRES; |
647 | } __packed; |
648 | |
649 | struct cntrl_cur_lay3 { |
650 | __le32 dCUR; |
651 | }; |
652 | |
653 | struct cntrl_subrange_lay3 { |
654 | __le32 dMIN; |
655 | __le32 dMAX; |
656 | __le32 dRES; |
657 | } __packed; |
658 | |
659 | #define ranges_lay3_size(c) (sizeof(c.wNumSubRanges) \ |
660 | + le16_to_cpu(c.wNumSubRanges) \ |
661 | * sizeof(struct cntrl_subrange_lay3)) |
662 | |
663 | #define DECLARE_UAC2_CNTRL_RANGES_LAY3(k, n) \ |
664 | struct cntrl_ranges_lay3_##k { \ |
665 | __le16 wNumSubRanges; \ |
666 | struct cntrl_subrange_lay3 r[n]; \ |
667 | } __packed |
668 | |
669 | DECLARE_UAC2_CNTRL_RANGES_LAY3(srates, UAC_MAX_RATES); |
670 | |
671 | static int get_max_srate(const int *srates) |
672 | { |
673 | int i, max_srate = 0; |
674 | |
675 | for (i = 0; i < UAC_MAX_RATES; i++) { |
676 | if (srates[i] == 0) |
677 | break; |
678 | if (srates[i] > max_srate) |
679 | max_srate = srates[i]; |
680 | } |
681 | return max_srate; |
682 | } |
683 | |
684 | static int get_max_bw_for_bint(const struct f_uac2_opts *uac2_opts, |
685 | u8 bint, unsigned int factor, bool is_playback) |
686 | { |
687 | int chmask, srate, ssize; |
688 | u16 max_size_bw; |
689 | |
690 | if (is_playback) { |
691 | chmask = uac2_opts->p_chmask; |
692 | srate = get_max_srate(srates: uac2_opts->p_srates); |
693 | ssize = uac2_opts->p_ssize; |
694 | } else { |
695 | chmask = uac2_opts->c_chmask; |
696 | srate = get_max_srate(srates: uac2_opts->c_srates); |
697 | ssize = uac2_opts->c_ssize; |
698 | } |
699 | |
700 | if (is_playback || (uac2_opts->c_sync == USB_ENDPOINT_SYNC_ASYNC)) { |
701 | // playback is always async, capture only when configured |
702 | // Win10 requires max packet size + 1 frame |
703 | srate = srate * (1000 + uac2_opts->fb_max) / 1000; |
704 | // updated srate is always bigger, therefore DIV_ROUND_UP always yields +1 |
705 | max_size_bw = num_channels(chanmask: chmask) * ssize * |
706 | (DIV_ROUND_UP(srate, factor / (1 << (bint - 1)))); |
707 | } else { |
708 | // adding 1 frame provision for Win10 |
709 | max_size_bw = num_channels(chanmask: chmask) * ssize * |
710 | (DIV_ROUND_UP(srate, factor / (1 << (bint - 1))) + 1); |
711 | } |
712 | return max_size_bw; |
713 | } |
714 | |
715 | static int set_ep_max_packet_size_bint(struct device *dev, const struct f_uac2_opts *uac2_opts, |
716 | struct usb_endpoint_descriptor *ep_desc, |
717 | enum usb_device_speed speed, bool is_playback) |
718 | { |
719 | u16 max_size_bw, max_size_ep; |
720 | u8 bint, opts_bint; |
721 | char *dir; |
722 | |
723 | switch (speed) { |
724 | case USB_SPEED_FULL: |
725 | max_size_ep = 1023; |
726 | // fixed |
727 | bint = ep_desc->bInterval; |
728 | max_size_bw = get_max_bw_for_bint(uac2_opts, bint, factor: 1000, is_playback); |
729 | break; |
730 | |
731 | case USB_SPEED_HIGH: |
732 | case USB_SPEED_SUPER: |
733 | max_size_ep = 1024; |
734 | if (is_playback) |
735 | opts_bint = uac2_opts->p_hs_bint; |
736 | else |
737 | opts_bint = uac2_opts->c_hs_bint; |
738 | |
739 | if (opts_bint > 0) { |
740 | /* fixed bint */ |
741 | bint = opts_bint; |
742 | max_size_bw = get_max_bw_for_bint(uac2_opts, bint, factor: 8000, is_playback); |
743 | } else { |
744 | /* checking bInterval from 4 to 1 whether the required bandwidth fits */ |
745 | for (bint = 4; bint > 0; --bint) { |
746 | max_size_bw = get_max_bw_for_bint( |
747 | uac2_opts, bint, factor: 8000, is_playback); |
748 | if (max_size_bw <= max_size_ep) |
749 | break; |
750 | } |
751 | } |
752 | break; |
753 | |
754 | default: |
755 | return -EINVAL; |
756 | } |
757 | |
758 | if (is_playback) |
759 | dir = "Playback" ; |
760 | else |
761 | dir = "Capture" ; |
762 | |
763 | if (max_size_bw <= max_size_ep) |
764 | dev_dbg(dev, |
765 | "%s %s: Would use wMaxPacketSize %d and bInterval %d\n" , |
766 | speed_names[speed], dir, max_size_bw, bint); |
767 | else { |
768 | dev_warn(dev, |
769 | "%s %s: Req. wMaxPacketSize %d at bInterval %d > max ISOC %d, may drop data!\n" , |
770 | speed_names[speed], dir, max_size_bw, bint, max_size_ep); |
771 | max_size_bw = max_size_ep; |
772 | } |
773 | |
774 | ep_desc->wMaxPacketSize = cpu_to_le16(max_size_bw); |
775 | ep_desc->bInterval = bint; |
776 | |
777 | return 0; |
778 | } |
779 | |
780 | static struct uac2_feature_unit_descriptor *build_fu_desc(int chmask) |
781 | { |
782 | struct uac2_feature_unit_descriptor *fu_desc; |
783 | int channels = num_channels(chanmask: chmask); |
784 | int fu_desc_size = UAC2_DT_FEATURE_UNIT_SIZE(channels); |
785 | |
786 | fu_desc = kzalloc(size: fu_desc_size, GFP_KERNEL); |
787 | if (!fu_desc) |
788 | return NULL; |
789 | |
790 | fu_desc->bLength = fu_desc_size; |
791 | fu_desc->bDescriptorType = USB_DT_CS_INTERFACE; |
792 | |
793 | fu_desc->bDescriptorSubtype = UAC_FEATURE_UNIT; |
794 | |
795 | /* bUnitID, bSourceID and bmaControls will be defined later */ |
796 | |
797 | return fu_desc; |
798 | } |
799 | |
800 | /* Use macro to overcome line length limitation */ |
801 | #define USBDHDR(p) (struct usb_descriptor_header *)(p) |
802 | |
803 | static void (struct f_uac2_opts *opts, |
804 | struct usb_descriptor_header **, |
805 | enum usb_device_speed speed) |
806 | { |
807 | struct usb_ss_ep_comp_descriptor *epout_desc_comp = NULL; |
808 | struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL; |
809 | struct usb_ss_ep_comp_descriptor *epin_fback_desc_comp = NULL; |
810 | struct usb_ss_ep_comp_descriptor *ep_int_desc_comp = NULL; |
811 | struct usb_endpoint_descriptor *epout_desc; |
812 | struct usb_endpoint_descriptor *epin_desc; |
813 | struct usb_endpoint_descriptor *epin_fback_desc; |
814 | struct usb_endpoint_descriptor *ep_int_desc; |
815 | int i; |
816 | |
817 | switch (speed) { |
818 | case USB_SPEED_FULL: |
819 | epout_desc = &fs_epout_desc; |
820 | epin_desc = &fs_epin_desc; |
821 | epin_fback_desc = &fs_epin_fback_desc; |
822 | ep_int_desc = &fs_ep_int_desc; |
823 | break; |
824 | case USB_SPEED_HIGH: |
825 | epout_desc = &hs_epout_desc; |
826 | epin_desc = &hs_epin_desc; |
827 | epin_fback_desc = &hs_epin_fback_desc; |
828 | ep_int_desc = &hs_ep_int_desc; |
829 | break; |
830 | default: |
831 | epout_desc = &ss_epout_desc; |
832 | epin_desc = &ss_epin_desc; |
833 | epout_desc_comp = &ss_epout_desc_comp; |
834 | epin_desc_comp = &ss_epin_desc_comp; |
835 | epin_fback_desc = &ss_epin_fback_desc; |
836 | epin_fback_desc_comp = &ss_epin_fback_desc_comp; |
837 | ep_int_desc = &ss_ep_int_desc; |
838 | ep_int_desc_comp = &ss_ep_int_desc_comp; |
839 | } |
840 | |
841 | i = 0; |
842 | headers[i++] = USBDHDR(&iad_desc); |
843 | headers[i++] = USBDHDR(&std_ac_if_desc); |
844 | headers[i++] = USBDHDR(&ac_hdr_desc); |
845 | if (EPIN_EN(opts)) |
846 | headers[i++] = USBDHDR(&in_clk_src_desc); |
847 | if (EPOUT_EN(opts)) { |
848 | headers[i++] = USBDHDR(&out_clk_src_desc); |
849 | headers[i++] = USBDHDR(&usb_out_it_desc); |
850 | |
851 | if (FUOUT_EN(opts)) |
852 | headers[i++] = USBDHDR(out_feature_unit_desc); |
853 | } |
854 | |
855 | if (EPIN_EN(opts)) { |
856 | headers[i++] = USBDHDR(&io_in_it_desc); |
857 | |
858 | if (FUIN_EN(opts)) |
859 | headers[i++] = USBDHDR(in_feature_unit_desc); |
860 | |
861 | headers[i++] = USBDHDR(&usb_in_ot_desc); |
862 | } |
863 | |
864 | if (EPOUT_EN(opts)) |
865 | headers[i++] = USBDHDR(&io_out_ot_desc); |
866 | |
867 | if (FUOUT_EN(opts) || FUIN_EN(opts)) { |
868 | headers[i++] = USBDHDR(ep_int_desc); |
869 | if (ep_int_desc_comp) |
870 | headers[i++] = USBDHDR(ep_int_desc_comp); |
871 | } |
872 | |
873 | if (EPOUT_EN(opts)) { |
874 | headers[i++] = USBDHDR(&std_as_out_if0_desc); |
875 | headers[i++] = USBDHDR(&std_as_out_if1_desc); |
876 | headers[i++] = USBDHDR(&as_out_hdr_desc); |
877 | headers[i++] = USBDHDR(&as_out_fmt1_desc); |
878 | headers[i++] = USBDHDR(epout_desc); |
879 | if (epout_desc_comp) |
880 | headers[i++] = USBDHDR(epout_desc_comp); |
881 | |
882 | headers[i++] = USBDHDR(&as_iso_out_desc); |
883 | |
884 | if (EPOUT_FBACK_IN_EN(opts)) { |
885 | headers[i++] = USBDHDR(epin_fback_desc); |
886 | if (epin_fback_desc_comp) |
887 | headers[i++] = USBDHDR(epin_fback_desc_comp); |
888 | } |
889 | } |
890 | |
891 | if (EPIN_EN(opts)) { |
892 | headers[i++] = USBDHDR(&std_as_in_if0_desc); |
893 | headers[i++] = USBDHDR(&std_as_in_if1_desc); |
894 | headers[i++] = USBDHDR(&as_in_hdr_desc); |
895 | headers[i++] = USBDHDR(&as_in_fmt1_desc); |
896 | headers[i++] = USBDHDR(epin_desc); |
897 | if (epin_desc_comp) |
898 | headers[i++] = USBDHDR(epin_desc_comp); |
899 | |
900 | headers[i++] = USBDHDR(&as_iso_in_desc); |
901 | } |
902 | headers[i] = NULL; |
903 | } |
904 | |
905 | static void setup_descriptor(struct f_uac2_opts *opts) |
906 | { |
907 | /* patch descriptors */ |
908 | int i = 1; /* ID's start with 1 */ |
909 | |
910 | if (EPOUT_EN(opts)) |
911 | usb_out_it_desc.bTerminalID = i++; |
912 | if (EPIN_EN(opts)) |
913 | io_in_it_desc.bTerminalID = i++; |
914 | if (EPOUT_EN(opts)) |
915 | io_out_ot_desc.bTerminalID = i++; |
916 | if (EPIN_EN(opts)) |
917 | usb_in_ot_desc.bTerminalID = i++; |
918 | if (FUOUT_EN(opts)) |
919 | out_feature_unit_desc->bUnitID = i++; |
920 | if (FUIN_EN(opts)) |
921 | in_feature_unit_desc->bUnitID = i++; |
922 | if (EPOUT_EN(opts)) |
923 | out_clk_src_desc.bClockID = i++; |
924 | if (EPIN_EN(opts)) |
925 | in_clk_src_desc.bClockID = i++; |
926 | |
927 | usb_out_it_desc.bCSourceID = out_clk_src_desc.bClockID; |
928 | |
929 | if (FUIN_EN(opts)) { |
930 | usb_in_ot_desc.bSourceID = in_feature_unit_desc->bUnitID; |
931 | in_feature_unit_desc->bSourceID = io_in_it_desc.bTerminalID; |
932 | } else { |
933 | usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID; |
934 | } |
935 | |
936 | usb_in_ot_desc.bCSourceID = in_clk_src_desc.bClockID; |
937 | io_in_it_desc.bCSourceID = in_clk_src_desc.bClockID; |
938 | io_out_ot_desc.bCSourceID = out_clk_src_desc.bClockID; |
939 | |
940 | if (FUOUT_EN(opts)) { |
941 | io_out_ot_desc.bSourceID = out_feature_unit_desc->bUnitID; |
942 | out_feature_unit_desc->bSourceID = usb_out_it_desc.bTerminalID; |
943 | } else { |
944 | io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID; |
945 | } |
946 | |
947 | as_out_hdr_desc.bTerminalLink = usb_out_it_desc.bTerminalID; |
948 | as_in_hdr_desc.bTerminalLink = usb_in_ot_desc.bTerminalID; |
949 | |
950 | iad_desc.bInterfaceCount = 1; |
951 | ac_hdr_desc.wTotalLength = cpu_to_le16(sizeof(ac_hdr_desc)); |
952 | |
953 | if (EPIN_EN(opts)) { |
954 | u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength); |
955 | |
956 | len += sizeof(in_clk_src_desc); |
957 | len += sizeof(usb_in_ot_desc); |
958 | |
959 | if (FUIN_EN(opts)) |
960 | len += in_feature_unit_desc->bLength; |
961 | |
962 | len += sizeof(io_in_it_desc); |
963 | ac_hdr_desc.wTotalLength = cpu_to_le16(len); |
964 | iad_desc.bInterfaceCount++; |
965 | } |
966 | if (EPOUT_EN(opts)) { |
967 | u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength); |
968 | |
969 | len += sizeof(out_clk_src_desc); |
970 | len += sizeof(usb_out_it_desc); |
971 | |
972 | if (FUOUT_EN(opts)) |
973 | len += out_feature_unit_desc->bLength; |
974 | |
975 | len += sizeof(io_out_ot_desc); |
976 | ac_hdr_desc.wTotalLength = cpu_to_le16(len); |
977 | iad_desc.bInterfaceCount++; |
978 | } |
979 | |
980 | io_in_it_desc.wTerminalType = cpu_to_le16(opts->c_terminal_type); |
981 | io_out_ot_desc.wTerminalType = cpu_to_le16(opts->p_terminal_type); |
982 | |
983 | setup_headers(opts, headers: fs_audio_desc, speed: USB_SPEED_FULL); |
984 | setup_headers(opts, headers: hs_audio_desc, speed: USB_SPEED_HIGH); |
985 | setup_headers(opts, headers: ss_audio_desc, speed: USB_SPEED_SUPER); |
986 | } |
987 | |
988 | static int afunc_validate_opts(struct g_audio *agdev, struct device *dev) |
989 | { |
990 | struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev); |
991 | const char *msg = NULL; |
992 | |
993 | if (!opts->p_chmask && !opts->c_chmask) |
994 | msg = "no playback and capture channels" ; |
995 | else if (opts->p_chmask & ~UAC2_CHANNEL_MASK) |
996 | msg = "unsupported playback channels mask" ; |
997 | else if (opts->c_chmask & ~UAC2_CHANNEL_MASK) |
998 | msg = "unsupported capture channels mask" ; |
999 | else if ((opts->p_ssize < 1) || (opts->p_ssize > 4)) |
1000 | msg = "incorrect playback sample size" ; |
1001 | else if ((opts->c_ssize < 1) || (opts->c_ssize > 4)) |
1002 | msg = "incorrect capture sample size" ; |
1003 | else if (!opts->p_srates[0]) |
1004 | msg = "incorrect playback sampling rate" ; |
1005 | else if (!opts->c_srates[0]) |
1006 | msg = "incorrect capture sampling rate" ; |
1007 | |
1008 | else if (opts->p_volume_max <= opts->p_volume_min) |
1009 | msg = "incorrect playback volume max/min" ; |
1010 | else if (opts->c_volume_max <= opts->c_volume_min) |
1011 | msg = "incorrect capture volume max/min" ; |
1012 | else if (opts->p_volume_res <= 0) |
1013 | msg = "negative/zero playback volume resolution" ; |
1014 | else if (opts->c_volume_res <= 0) |
1015 | msg = "negative/zero capture volume resolution" ; |
1016 | |
1017 | else if ((opts->p_volume_max - opts->p_volume_min) % opts->p_volume_res) |
1018 | msg = "incorrect playback volume resolution" ; |
1019 | else if ((opts->c_volume_max - opts->c_volume_min) % opts->c_volume_res) |
1020 | msg = "incorrect capture volume resolution" ; |
1021 | |
1022 | else if ((opts->p_hs_bint < 0) || (opts->p_hs_bint > 4)) |
1023 | msg = "incorrect playback HS/SS bInterval (1-4: fixed, 0: auto)" ; |
1024 | else if ((opts->c_hs_bint < 0) || (opts->c_hs_bint > 4)) |
1025 | msg = "incorrect capture HS/SS bInterval (1-4: fixed, 0: auto)" ; |
1026 | |
1027 | if (msg) { |
1028 | dev_err(dev, "Error: %s\n" , msg); |
1029 | return -EINVAL; |
1030 | } |
1031 | |
1032 | return 0; |
1033 | } |
1034 | |
1035 | static int |
1036 | afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) |
1037 | { |
1038 | struct f_uac2 *uac2 = func_to_uac2(f: fn); |
1039 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1040 | struct usb_composite_dev *cdev = cfg->cdev; |
1041 | struct usb_gadget *gadget = cdev->gadget; |
1042 | struct device *dev = &gadget->dev; |
1043 | struct f_uac2_opts *uac2_opts = g_audio_to_uac2_opts(agdev); |
1044 | struct usb_string *us; |
1045 | int ret; |
1046 | |
1047 | ret = afunc_validate_opts(agdev, dev); |
1048 | if (ret) |
1049 | return ret; |
1050 | |
1051 | strings_fn[STR_ASSOC].s = uac2_opts->function_name; |
1052 | |
1053 | us = usb_gstrings_attach(cdev, sp: fn_strings, ARRAY_SIZE(strings_fn)); |
1054 | if (IS_ERR(ptr: us)) |
1055 | return PTR_ERR(ptr: us); |
1056 | |
1057 | if (FUOUT_EN(uac2_opts)) { |
1058 | out_feature_unit_desc = build_fu_desc(chmask: uac2_opts->c_chmask); |
1059 | if (!out_feature_unit_desc) |
1060 | return -ENOMEM; |
1061 | } |
1062 | if (FUIN_EN(uac2_opts)) { |
1063 | in_feature_unit_desc = build_fu_desc(chmask: uac2_opts->p_chmask); |
1064 | if (!in_feature_unit_desc) { |
1065 | ret = -ENOMEM; |
1066 | goto err_free_fu; |
1067 | } |
1068 | } |
1069 | |
1070 | iad_desc.iFunction = us[STR_ASSOC].id; |
1071 | std_ac_if_desc.iInterface = us[STR_IF_CTRL].id; |
1072 | in_clk_src_desc.iClockSource = us[STR_CLKSRC_IN].id; |
1073 | out_clk_src_desc.iClockSource = us[STR_CLKSRC_OUT].id; |
1074 | usb_out_it_desc.iTerminal = us[STR_USB_IT].id; |
1075 | io_in_it_desc.iTerminal = us[STR_IO_IT].id; |
1076 | usb_in_ot_desc.iTerminal = us[STR_USB_OT].id; |
1077 | io_out_ot_desc.iTerminal = us[STR_IO_OT].id; |
1078 | std_as_out_if0_desc.iInterface = us[STR_AS_OUT_ALT0].id; |
1079 | std_as_out_if1_desc.iInterface = us[STR_AS_OUT_ALT1].id; |
1080 | std_as_in_if0_desc.iInterface = us[STR_AS_IN_ALT0].id; |
1081 | std_as_in_if1_desc.iInterface = us[STR_AS_IN_ALT1].id; |
1082 | |
1083 | if (FUOUT_EN(uac2_opts)) { |
1084 | u8 *i_feature = (u8 *)out_feature_unit_desc + |
1085 | out_feature_unit_desc->bLength - 1; |
1086 | *i_feature = us[STR_FU_OUT].id; |
1087 | } |
1088 | if (FUIN_EN(uac2_opts)) { |
1089 | u8 *i_feature = (u8 *)in_feature_unit_desc + |
1090 | in_feature_unit_desc->bLength - 1; |
1091 | *i_feature = us[STR_FU_IN].id; |
1092 | } |
1093 | |
1094 | |
1095 | /* Initialize the configurable parameters */ |
1096 | usb_out_it_desc.bNrChannels = num_channels(chanmask: uac2_opts->c_chmask); |
1097 | usb_out_it_desc.bmChannelConfig = cpu_to_le32(uac2_opts->c_chmask); |
1098 | io_in_it_desc.bNrChannels = num_channels(chanmask: uac2_opts->p_chmask); |
1099 | io_in_it_desc.bmChannelConfig = cpu_to_le32(uac2_opts->p_chmask); |
1100 | as_out_hdr_desc.bNrChannels = num_channels(chanmask: uac2_opts->c_chmask); |
1101 | as_out_hdr_desc.bmChannelConfig = cpu_to_le32(uac2_opts->c_chmask); |
1102 | as_in_hdr_desc.bNrChannels = num_channels(chanmask: uac2_opts->p_chmask); |
1103 | as_in_hdr_desc.bmChannelConfig = cpu_to_le32(uac2_opts->p_chmask); |
1104 | as_out_fmt1_desc.bSubslotSize = uac2_opts->c_ssize; |
1105 | as_out_fmt1_desc.bBitResolution = uac2_opts->c_ssize * 8; |
1106 | as_in_fmt1_desc.bSubslotSize = uac2_opts->p_ssize; |
1107 | as_in_fmt1_desc.bBitResolution = uac2_opts->p_ssize * 8; |
1108 | if (FUOUT_EN(uac2_opts)) { |
1109 | __le32 *bma = (__le32 *)&out_feature_unit_desc->bmaControls[0]; |
1110 | u32 control = 0; |
1111 | |
1112 | if (uac2_opts->c_mute_present) |
1113 | control |= CONTROL_RDWR << FU_MUTE_CTRL; |
1114 | if (uac2_opts->c_volume_present) |
1115 | control |= CONTROL_RDWR << FU_VOL_CTRL; |
1116 | *bma = cpu_to_le32(control); |
1117 | } |
1118 | if (FUIN_EN(uac2_opts)) { |
1119 | __le32 *bma = (__le32 *)&in_feature_unit_desc->bmaControls[0]; |
1120 | u32 control = 0; |
1121 | |
1122 | if (uac2_opts->p_mute_present) |
1123 | control |= CONTROL_RDWR << FU_MUTE_CTRL; |
1124 | if (uac2_opts->p_volume_present) |
1125 | control |= CONTROL_RDWR << FU_VOL_CTRL; |
1126 | *bma = cpu_to_le32(control); |
1127 | } |
1128 | |
1129 | ret = usb_interface_id(cfg, fn); |
1130 | if (ret < 0) { |
1131 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1132 | goto err_free_fu; |
1133 | } |
1134 | iad_desc.bFirstInterface = ret; |
1135 | |
1136 | std_ac_if_desc.bInterfaceNumber = ret; |
1137 | uac2->ac_intf = ret; |
1138 | uac2->ac_alt = 0; |
1139 | |
1140 | if (EPOUT_EN(uac2_opts)) { |
1141 | ret = usb_interface_id(cfg, fn); |
1142 | if (ret < 0) { |
1143 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1144 | goto err_free_fu; |
1145 | } |
1146 | std_as_out_if0_desc.bInterfaceNumber = ret; |
1147 | std_as_out_if1_desc.bInterfaceNumber = ret; |
1148 | std_as_out_if1_desc.bNumEndpoints = 1; |
1149 | uac2->as_out_intf = ret; |
1150 | uac2->as_out_alt = 0; |
1151 | |
1152 | if (EPOUT_FBACK_IN_EN(uac2_opts)) { |
1153 | fs_epout_desc.bmAttributes = |
1154 | USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC; |
1155 | hs_epout_desc.bmAttributes = |
1156 | USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC; |
1157 | ss_epout_desc.bmAttributes = |
1158 | USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC; |
1159 | std_as_out_if1_desc.bNumEndpoints++; |
1160 | } else { |
1161 | fs_epout_desc.bmAttributes = |
1162 | USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ADAPTIVE; |
1163 | hs_epout_desc.bmAttributes = |
1164 | USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ADAPTIVE; |
1165 | ss_epout_desc.bmAttributes = |
1166 | USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ADAPTIVE; |
1167 | } |
1168 | } |
1169 | |
1170 | if (EPIN_EN(uac2_opts)) { |
1171 | ret = usb_interface_id(cfg, fn); |
1172 | if (ret < 0) { |
1173 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1174 | goto err_free_fu; |
1175 | } |
1176 | std_as_in_if0_desc.bInterfaceNumber = ret; |
1177 | std_as_in_if1_desc.bInterfaceNumber = ret; |
1178 | uac2->as_in_intf = ret; |
1179 | uac2->as_in_alt = 0; |
1180 | } |
1181 | |
1182 | if (FUOUT_EN(uac2_opts) || FUIN_EN(uac2_opts)) { |
1183 | uac2->int_ep = usb_ep_autoconfig(gadget, &fs_ep_int_desc); |
1184 | if (!uac2->int_ep) { |
1185 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1186 | ret = -ENODEV; |
1187 | goto err_free_fu; |
1188 | } |
1189 | |
1190 | std_ac_if_desc.bNumEndpoints = 1; |
1191 | } |
1192 | |
1193 | hs_epin_desc.bInterval = uac2_opts->p_hs_bint; |
1194 | ss_epin_desc.bInterval = uac2_opts->p_hs_bint; |
1195 | hs_epout_desc.bInterval = uac2_opts->c_hs_bint; |
1196 | ss_epout_desc.bInterval = uac2_opts->c_hs_bint; |
1197 | |
1198 | /* Calculate wMaxPacketSize according to audio bandwidth */ |
1199 | ret = set_ep_max_packet_size_bint(dev, uac2_opts, ep_desc: &fs_epin_desc, |
1200 | speed: USB_SPEED_FULL, is_playback: true); |
1201 | if (ret < 0) { |
1202 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1203 | return ret; |
1204 | } |
1205 | |
1206 | ret = set_ep_max_packet_size_bint(dev, uac2_opts, ep_desc: &fs_epout_desc, |
1207 | speed: USB_SPEED_FULL, is_playback: false); |
1208 | if (ret < 0) { |
1209 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1210 | return ret; |
1211 | } |
1212 | |
1213 | ret = set_ep_max_packet_size_bint(dev, uac2_opts, ep_desc: &hs_epin_desc, |
1214 | speed: USB_SPEED_HIGH, is_playback: true); |
1215 | if (ret < 0) { |
1216 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1217 | return ret; |
1218 | } |
1219 | |
1220 | ret = set_ep_max_packet_size_bint(dev, uac2_opts, ep_desc: &hs_epout_desc, |
1221 | speed: USB_SPEED_HIGH, is_playback: false); |
1222 | if (ret < 0) { |
1223 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1224 | return ret; |
1225 | } |
1226 | |
1227 | ret = set_ep_max_packet_size_bint(dev, uac2_opts, ep_desc: &ss_epin_desc, |
1228 | speed: USB_SPEED_SUPER, is_playback: true); |
1229 | if (ret < 0) { |
1230 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1231 | return ret; |
1232 | } |
1233 | |
1234 | ret = set_ep_max_packet_size_bint(dev, uac2_opts, ep_desc: &ss_epout_desc, |
1235 | speed: USB_SPEED_SUPER, is_playback: false); |
1236 | if (ret < 0) { |
1237 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1238 | return ret; |
1239 | } |
1240 | |
1241 | if (EPOUT_EN(uac2_opts)) { |
1242 | agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); |
1243 | if (!agdev->out_ep) { |
1244 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1245 | ret = -ENODEV; |
1246 | goto err_free_fu; |
1247 | } |
1248 | if (EPOUT_FBACK_IN_EN(uac2_opts)) { |
1249 | agdev->in_ep_fback = usb_ep_autoconfig(gadget, |
1250 | &fs_epin_fback_desc); |
1251 | if (!agdev->in_ep_fback) { |
1252 | dev_err(dev, "%s:%d Error!\n" , |
1253 | __func__, __LINE__); |
1254 | ret = -ENODEV; |
1255 | goto err_free_fu; |
1256 | } |
1257 | } |
1258 | } |
1259 | |
1260 | if (EPIN_EN(uac2_opts)) { |
1261 | agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); |
1262 | if (!agdev->in_ep) { |
1263 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1264 | ret = -ENODEV; |
1265 | goto err_free_fu; |
1266 | } |
1267 | } |
1268 | |
1269 | agdev->in_ep_maxpsize = max_t(u16, |
1270 | le16_to_cpu(fs_epin_desc.wMaxPacketSize), |
1271 | le16_to_cpu(hs_epin_desc.wMaxPacketSize)); |
1272 | agdev->out_ep_maxpsize = max_t(u16, |
1273 | le16_to_cpu(fs_epout_desc.wMaxPacketSize), |
1274 | le16_to_cpu(hs_epout_desc.wMaxPacketSize)); |
1275 | |
1276 | agdev->in_ep_maxpsize = max_t(u16, agdev->in_ep_maxpsize, |
1277 | le16_to_cpu(ss_epin_desc.wMaxPacketSize)); |
1278 | agdev->out_ep_maxpsize = max_t(u16, agdev->out_ep_maxpsize, |
1279 | le16_to_cpu(ss_epout_desc.wMaxPacketSize)); |
1280 | |
1281 | ss_epin_desc_comp.wBytesPerInterval = ss_epin_desc.wMaxPacketSize; |
1282 | ss_epout_desc_comp.wBytesPerInterval = ss_epout_desc.wMaxPacketSize; |
1283 | |
1284 | // HS and SS endpoint addresses are copied from autoconfigured FS descriptors |
1285 | hs_ep_int_desc.bEndpointAddress = fs_ep_int_desc.bEndpointAddress; |
1286 | hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; |
1287 | hs_epin_fback_desc.bEndpointAddress = fs_epin_fback_desc.bEndpointAddress; |
1288 | hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; |
1289 | ss_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; |
1290 | ss_epin_fback_desc.bEndpointAddress = fs_epin_fback_desc.bEndpointAddress; |
1291 | ss_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; |
1292 | ss_ep_int_desc.bEndpointAddress = fs_ep_int_desc.bEndpointAddress; |
1293 | |
1294 | setup_descriptor(uac2_opts); |
1295 | |
1296 | ret = usb_assign_descriptors(f: fn, fs: fs_audio_desc, hs: hs_audio_desc, ss: ss_audio_desc, |
1297 | ssp: ss_audio_desc); |
1298 | if (ret) |
1299 | goto err_free_fu; |
1300 | |
1301 | agdev->gadget = gadget; |
1302 | |
1303 | agdev->params.p_chmask = uac2_opts->p_chmask; |
1304 | memcpy(agdev->params.p_srates, uac2_opts->p_srates, |
1305 | sizeof(agdev->params.p_srates)); |
1306 | agdev->params.p_ssize = uac2_opts->p_ssize; |
1307 | if (FUIN_EN(uac2_opts)) { |
1308 | agdev->params.p_fu.id = USB_IN_FU_ID; |
1309 | agdev->params.p_fu.mute_present = uac2_opts->p_mute_present; |
1310 | agdev->params.p_fu.volume_present = uac2_opts->p_volume_present; |
1311 | agdev->params.p_fu.volume_min = uac2_opts->p_volume_min; |
1312 | agdev->params.p_fu.volume_max = uac2_opts->p_volume_max; |
1313 | agdev->params.p_fu.volume_res = uac2_opts->p_volume_res; |
1314 | } |
1315 | agdev->params.c_chmask = uac2_opts->c_chmask; |
1316 | memcpy(agdev->params.c_srates, uac2_opts->c_srates, |
1317 | sizeof(agdev->params.c_srates)); |
1318 | agdev->params.c_ssize = uac2_opts->c_ssize; |
1319 | if (FUOUT_EN(uac2_opts)) { |
1320 | agdev->params.c_fu.id = USB_OUT_FU_ID; |
1321 | agdev->params.c_fu.mute_present = uac2_opts->c_mute_present; |
1322 | agdev->params.c_fu.volume_present = uac2_opts->c_volume_present; |
1323 | agdev->params.c_fu.volume_min = uac2_opts->c_volume_min; |
1324 | agdev->params.c_fu.volume_max = uac2_opts->c_volume_max; |
1325 | agdev->params.c_fu.volume_res = uac2_opts->c_volume_res; |
1326 | } |
1327 | agdev->params.req_number = uac2_opts->req_number; |
1328 | agdev->params.fb_max = uac2_opts->fb_max; |
1329 | |
1330 | if (FUOUT_EN(uac2_opts) || FUIN_EN(uac2_opts)) |
1331 | agdev->notify = afunc_notify; |
1332 | |
1333 | ret = g_audio_setup(g_audio: agdev, pcm_name: "UAC2 PCM" , card_name: "UAC2_Gadget" ); |
1334 | if (ret) |
1335 | goto err_free_descs; |
1336 | |
1337 | return 0; |
1338 | |
1339 | err_free_descs: |
1340 | usb_free_all_descriptors(f: fn); |
1341 | agdev->gadget = NULL; |
1342 | err_free_fu: |
1343 | kfree(objp: out_feature_unit_desc); |
1344 | out_feature_unit_desc = NULL; |
1345 | kfree(objp: in_feature_unit_desc); |
1346 | in_feature_unit_desc = NULL; |
1347 | return ret; |
1348 | } |
1349 | |
1350 | static void |
1351 | afunc_notify_complete(struct usb_ep *_ep, struct usb_request *req) |
1352 | { |
1353 | struct g_audio *agdev = req->context; |
1354 | struct f_uac2 *uac2 = func_to_uac2(f: &agdev->func); |
1355 | |
1356 | atomic_dec(v: &uac2->int_count); |
1357 | kfree(objp: req->buf); |
1358 | usb_ep_free_request(ep: _ep, req); |
1359 | } |
1360 | |
1361 | static int |
1362 | afunc_notify(struct g_audio *agdev, int unit_id, int cs) |
1363 | { |
1364 | struct f_uac2 *uac2 = func_to_uac2(f: &agdev->func); |
1365 | struct usb_request *req; |
1366 | struct uac2_interrupt_data_msg *msg; |
1367 | u16 w_index, w_value; |
1368 | int ret; |
1369 | |
1370 | if (!uac2->int_ep->enabled) |
1371 | return 0; |
1372 | |
1373 | if (atomic_inc_return(v: &uac2->int_count) > UAC2_DEF_INT_REQ_NUM) { |
1374 | atomic_dec(v: &uac2->int_count); |
1375 | return 0; |
1376 | } |
1377 | |
1378 | req = usb_ep_alloc_request(ep: uac2->int_ep, GFP_ATOMIC); |
1379 | if (req == NULL) { |
1380 | ret = -ENOMEM; |
1381 | goto err_dec_int_count; |
1382 | } |
1383 | |
1384 | msg = kzalloc(size: sizeof(*msg), GFP_ATOMIC); |
1385 | if (msg == NULL) { |
1386 | ret = -ENOMEM; |
1387 | goto err_free_request; |
1388 | } |
1389 | |
1390 | w_index = unit_id << 8 | uac2->ac_intf; |
1391 | w_value = cs << 8; |
1392 | |
1393 | msg->bInfo = 0; /* Non-vendor, interface interrupt */ |
1394 | msg->bAttribute = UAC2_CS_CUR; |
1395 | msg->wIndex = cpu_to_le16(w_index); |
1396 | msg->wValue = cpu_to_le16(w_value); |
1397 | |
1398 | req->length = sizeof(*msg); |
1399 | req->buf = msg; |
1400 | req->context = agdev; |
1401 | req->complete = afunc_notify_complete; |
1402 | |
1403 | ret = usb_ep_queue(ep: uac2->int_ep, req, GFP_ATOMIC); |
1404 | |
1405 | if (ret) |
1406 | goto err_free_msg; |
1407 | |
1408 | return 0; |
1409 | |
1410 | err_free_msg: |
1411 | kfree(objp: msg); |
1412 | err_free_request: |
1413 | usb_ep_free_request(ep: uac2->int_ep, req); |
1414 | err_dec_int_count: |
1415 | atomic_dec(v: &uac2->int_count); |
1416 | |
1417 | return ret; |
1418 | } |
1419 | |
1420 | static int |
1421 | afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) |
1422 | { |
1423 | struct usb_composite_dev *cdev = fn->config->cdev; |
1424 | struct f_uac2 *uac2 = func_to_uac2(f: fn); |
1425 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1426 | struct usb_gadget *gadget = cdev->gadget; |
1427 | struct device *dev = &gadget->dev; |
1428 | int ret = 0; |
1429 | |
1430 | /* No i/f has more than 2 alt settings */ |
1431 | if (alt > 1) { |
1432 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1433 | return -EINVAL; |
1434 | } |
1435 | |
1436 | if (intf == uac2->ac_intf) { |
1437 | /* Control I/f has only 1 AltSetting - 0 */ |
1438 | if (alt) { |
1439 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1440 | return -EINVAL; |
1441 | } |
1442 | |
1443 | /* restart interrupt endpoint */ |
1444 | if (uac2->int_ep) { |
1445 | usb_ep_disable(ep: uac2->int_ep); |
1446 | config_ep_by_speed(g: gadget, f: &agdev->func, ep: uac2->int_ep); |
1447 | usb_ep_enable(ep: uac2->int_ep); |
1448 | } |
1449 | |
1450 | return 0; |
1451 | } |
1452 | |
1453 | if (intf == uac2->as_out_intf) { |
1454 | uac2->as_out_alt = alt; |
1455 | |
1456 | if (alt) |
1457 | ret = u_audio_start_capture(g_audio: &uac2->g_audio); |
1458 | else |
1459 | u_audio_stop_capture(g_audio: &uac2->g_audio); |
1460 | } else if (intf == uac2->as_in_intf) { |
1461 | uac2->as_in_alt = alt; |
1462 | |
1463 | if (alt) |
1464 | ret = u_audio_start_playback(g_audio: &uac2->g_audio); |
1465 | else |
1466 | u_audio_stop_playback(g_audio: &uac2->g_audio); |
1467 | } else { |
1468 | dev_err(dev, "%s:%d Error!\n" , __func__, __LINE__); |
1469 | return -EINVAL; |
1470 | } |
1471 | |
1472 | return ret; |
1473 | } |
1474 | |
1475 | static int |
1476 | afunc_get_alt(struct usb_function *fn, unsigned intf) |
1477 | { |
1478 | struct f_uac2 *uac2 = func_to_uac2(f: fn); |
1479 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1480 | |
1481 | if (intf == uac2->ac_intf) |
1482 | return uac2->ac_alt; |
1483 | else if (intf == uac2->as_out_intf) |
1484 | return uac2->as_out_alt; |
1485 | else if (intf == uac2->as_in_intf) |
1486 | return uac2->as_in_alt; |
1487 | else |
1488 | dev_err(&agdev->gadget->dev, |
1489 | "%s:%d Invalid Interface %d!\n" , |
1490 | __func__, __LINE__, intf); |
1491 | |
1492 | return -EINVAL; |
1493 | } |
1494 | |
1495 | static void |
1496 | afunc_disable(struct usb_function *fn) |
1497 | { |
1498 | struct f_uac2 *uac2 = func_to_uac2(f: fn); |
1499 | |
1500 | uac2->as_in_alt = 0; |
1501 | uac2->as_out_alt = 0; |
1502 | u_audio_stop_capture(g_audio: &uac2->g_audio); |
1503 | u_audio_stop_playback(g_audio: &uac2->g_audio); |
1504 | if (uac2->int_ep) |
1505 | usb_ep_disable(ep: uac2->int_ep); |
1506 | } |
1507 | |
1508 | static void |
1509 | afunc_suspend(struct usb_function *fn) |
1510 | { |
1511 | struct f_uac2 *uac2 = func_to_uac2(f: fn); |
1512 | |
1513 | u_audio_suspend(g_audio: &uac2->g_audio); |
1514 | } |
1515 | |
1516 | static int |
1517 | in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) |
1518 | { |
1519 | struct usb_request *req = fn->config->cdev->req; |
1520 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1521 | struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev); |
1522 | u16 w_length = le16_to_cpu(cr->wLength); |
1523 | u16 w_index = le16_to_cpu(cr->wIndex); |
1524 | u16 w_value = le16_to_cpu(cr->wValue); |
1525 | u8 entity_id = (w_index >> 8) & 0xff; |
1526 | u8 control_selector = w_value >> 8; |
1527 | int value = -EOPNOTSUPP; |
1528 | u32 p_srate, c_srate; |
1529 | |
1530 | u_audio_get_playback_srate(audio_dev: agdev, val: &p_srate); |
1531 | u_audio_get_capture_srate(audio_dev: agdev, val: &c_srate); |
1532 | |
1533 | if ((entity_id == USB_IN_CLK_ID) || (entity_id == USB_OUT_CLK_ID)) { |
1534 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { |
1535 | struct cntrl_cur_lay3 c; |
1536 | |
1537 | memset(&c, 0, sizeof(struct cntrl_cur_lay3)); |
1538 | |
1539 | if (entity_id == USB_IN_CLK_ID) |
1540 | c.dCUR = cpu_to_le32(p_srate); |
1541 | else if (entity_id == USB_OUT_CLK_ID) |
1542 | c.dCUR = cpu_to_le32(c_srate); |
1543 | |
1544 | value = min_t(unsigned int, w_length, sizeof(c)); |
1545 | memcpy(req->buf, &c, value); |
1546 | } else if (control_selector == UAC2_CS_CONTROL_CLOCK_VALID) { |
1547 | *(u8 *)req->buf = 1; |
1548 | value = min_t(unsigned int, w_length, 1); |
1549 | } else { |
1550 | dev_err(&agdev->gadget->dev, |
1551 | "%s:%d control_selector=%d TODO!\n" , |
1552 | __func__, __LINE__, control_selector); |
1553 | } |
1554 | } else if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) || |
1555 | (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) { |
1556 | unsigned int is_playback = 0; |
1557 | |
1558 | if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) |
1559 | is_playback = 1; |
1560 | |
1561 | if (control_selector == UAC_FU_MUTE) { |
1562 | unsigned int mute; |
1563 | |
1564 | u_audio_get_mute(g_audio: agdev, playback: is_playback, val: &mute); |
1565 | |
1566 | *(u8 *)req->buf = mute; |
1567 | value = min_t(unsigned int, w_length, 1); |
1568 | } else if (control_selector == UAC_FU_VOLUME) { |
1569 | struct cntrl_cur_lay2 c; |
1570 | s16 volume; |
1571 | |
1572 | memset(&c, 0, sizeof(struct cntrl_cur_lay2)); |
1573 | |
1574 | u_audio_get_volume(g_audio: agdev, playback: is_playback, val: &volume); |
1575 | c.wCUR = cpu_to_le16(volume); |
1576 | |
1577 | value = min_t(unsigned int, w_length, sizeof(c)); |
1578 | memcpy(req->buf, &c, value); |
1579 | } else { |
1580 | dev_err(&agdev->gadget->dev, |
1581 | "%s:%d control_selector=%d TODO!\n" , |
1582 | __func__, __LINE__, control_selector); |
1583 | } |
1584 | } else { |
1585 | dev_err(&agdev->gadget->dev, |
1586 | "%s:%d entity_id=%d control_selector=%d TODO!\n" , |
1587 | __func__, __LINE__, entity_id, control_selector); |
1588 | } |
1589 | |
1590 | return value; |
1591 | } |
1592 | |
1593 | static int |
1594 | in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) |
1595 | { |
1596 | struct usb_request *req = fn->config->cdev->req; |
1597 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1598 | struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev); |
1599 | u16 w_length = le16_to_cpu(cr->wLength); |
1600 | u16 w_index = le16_to_cpu(cr->wIndex); |
1601 | u16 w_value = le16_to_cpu(cr->wValue); |
1602 | u8 entity_id = (w_index >> 8) & 0xff; |
1603 | u8 control_selector = w_value >> 8; |
1604 | int value = -EOPNOTSUPP; |
1605 | |
1606 | if ((entity_id == USB_IN_CLK_ID) || (entity_id == USB_OUT_CLK_ID)) { |
1607 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { |
1608 | struct cntrl_ranges_lay3_srates rs; |
1609 | int i; |
1610 | int wNumSubRanges = 0; |
1611 | int srate; |
1612 | int *srates; |
1613 | |
1614 | if (entity_id == USB_IN_CLK_ID) |
1615 | srates = opts->p_srates; |
1616 | else if (entity_id == USB_OUT_CLK_ID) |
1617 | srates = opts->c_srates; |
1618 | else |
1619 | return -EOPNOTSUPP; |
1620 | for (i = 0; i < UAC_MAX_RATES; i++) { |
1621 | srate = srates[i]; |
1622 | if (srate == 0) |
1623 | break; |
1624 | |
1625 | rs.r[wNumSubRanges].dMIN = cpu_to_le32(srate); |
1626 | rs.r[wNumSubRanges].dMAX = cpu_to_le32(srate); |
1627 | rs.r[wNumSubRanges].dRES = 0; |
1628 | wNumSubRanges++; |
1629 | dev_dbg(&agdev->gadget->dev, |
1630 | "%s(): clk %d: rate ID %d: %d\n" , |
1631 | __func__, entity_id, wNumSubRanges, srate); |
1632 | } |
1633 | rs.wNumSubRanges = cpu_to_le16(wNumSubRanges); |
1634 | value = min_t(unsigned int, w_length, ranges_lay3_size(rs)); |
1635 | dev_dbg(&agdev->gadget->dev, "%s(): sending %d rates, size %d\n" , |
1636 | __func__, rs.wNumSubRanges, value); |
1637 | memcpy(req->buf, &rs, value); |
1638 | } else { |
1639 | dev_err(&agdev->gadget->dev, |
1640 | "%s:%d control_selector=%d TODO!\n" , |
1641 | __func__, __LINE__, control_selector); |
1642 | } |
1643 | } else if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) || |
1644 | (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) { |
1645 | unsigned int is_playback = 0; |
1646 | |
1647 | if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) |
1648 | is_playback = 1; |
1649 | |
1650 | if (control_selector == UAC_FU_VOLUME) { |
1651 | struct cntrl_range_lay2 r; |
1652 | s16 max_db, min_db, res_db; |
1653 | |
1654 | if (is_playback) { |
1655 | max_db = opts->p_volume_max; |
1656 | min_db = opts->p_volume_min; |
1657 | res_db = opts->p_volume_res; |
1658 | } else { |
1659 | max_db = opts->c_volume_max; |
1660 | min_db = opts->c_volume_min; |
1661 | res_db = opts->c_volume_res; |
1662 | } |
1663 | |
1664 | r.wMAX = cpu_to_le16(max_db); |
1665 | r.wMIN = cpu_to_le16(min_db); |
1666 | r.wRES = cpu_to_le16(res_db); |
1667 | r.wNumSubRanges = cpu_to_le16(1); |
1668 | |
1669 | value = min_t(unsigned int, w_length, sizeof(r)); |
1670 | memcpy(req->buf, &r, value); |
1671 | } else { |
1672 | dev_err(&agdev->gadget->dev, |
1673 | "%s:%d control_selector=%d TODO!\n" , |
1674 | __func__, __LINE__, control_selector); |
1675 | } |
1676 | } else { |
1677 | dev_err(&agdev->gadget->dev, |
1678 | "%s:%d entity_id=%d control_selector=%d TODO!\n" , |
1679 | __func__, __LINE__, entity_id, control_selector); |
1680 | } |
1681 | |
1682 | return value; |
1683 | } |
1684 | |
1685 | static int |
1686 | ac_rq_in(struct usb_function *fn, const struct usb_ctrlrequest *cr) |
1687 | { |
1688 | if (cr->bRequest == UAC2_CS_CUR) |
1689 | return in_rq_cur(fn, cr); |
1690 | else if (cr->bRequest == UAC2_CS_RANGE) |
1691 | return in_rq_range(fn, cr); |
1692 | else |
1693 | return -EOPNOTSUPP; |
1694 | } |
1695 | |
1696 | static void uac2_cs_control_sam_freq(struct usb_ep *ep, struct usb_request *req) |
1697 | { |
1698 | struct usb_function *fn = ep->driver_data; |
1699 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1700 | struct f_uac2 *uac2 = func_to_uac2(f: fn); |
1701 | u32 val; |
1702 | |
1703 | if (req->actual != 4) |
1704 | return; |
1705 | |
1706 | val = le32_to_cpu(*((__le32 *)req->buf)); |
1707 | dev_dbg(&agdev->gadget->dev, "%s val: %d.\n" , __func__, val); |
1708 | if (uac2->clock_id == USB_IN_CLK_ID) { |
1709 | u_audio_set_playback_srate(audio_dev: agdev, srate: val); |
1710 | } else if (uac2->clock_id == USB_OUT_CLK_ID) { |
1711 | u_audio_set_capture_srate(audio_dev: agdev, srate: val); |
1712 | } |
1713 | } |
1714 | |
1715 | static void |
1716 | out_rq_cur_complete(struct usb_ep *ep, struct usb_request *req) |
1717 | { |
1718 | struct g_audio *agdev = req->context; |
1719 | struct usb_composite_dev *cdev = agdev->func.config->cdev; |
1720 | struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev); |
1721 | struct f_uac2 *uac2 = func_to_uac2(f: &agdev->func); |
1722 | struct usb_ctrlrequest *cr = &uac2->setup_cr; |
1723 | u16 w_index = le16_to_cpu(cr->wIndex); |
1724 | u16 w_value = le16_to_cpu(cr->wValue); |
1725 | u8 entity_id = (w_index >> 8) & 0xff; |
1726 | u8 control_selector = w_value >> 8; |
1727 | |
1728 | if (req->status != 0) { |
1729 | dev_dbg(&cdev->gadget->dev, "completion err %d\n" , req->status); |
1730 | return; |
1731 | } |
1732 | |
1733 | if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) || |
1734 | (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) { |
1735 | unsigned int is_playback = 0; |
1736 | |
1737 | if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) |
1738 | is_playback = 1; |
1739 | |
1740 | if (control_selector == UAC_FU_MUTE) { |
1741 | u8 mute = *(u8 *)req->buf; |
1742 | |
1743 | u_audio_set_mute(g_audio: agdev, playback: is_playback, val: mute); |
1744 | |
1745 | return; |
1746 | } else if (control_selector == UAC_FU_VOLUME) { |
1747 | struct cntrl_cur_lay2 *c = req->buf; |
1748 | s16 volume; |
1749 | |
1750 | volume = le16_to_cpu(c->wCUR); |
1751 | u_audio_set_volume(g_audio: agdev, playback: is_playback, val: volume); |
1752 | |
1753 | return; |
1754 | } else { |
1755 | dev_err(&agdev->gadget->dev, |
1756 | "%s:%d control_selector=%d TODO!\n" , |
1757 | __func__, __LINE__, control_selector); |
1758 | usb_ep_set_halt(ep); |
1759 | } |
1760 | } |
1761 | } |
1762 | |
1763 | static int |
1764 | out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) |
1765 | { |
1766 | struct usb_composite_dev *cdev = fn->config->cdev; |
1767 | struct usb_request *req = fn->config->cdev->req; |
1768 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1769 | struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev); |
1770 | struct f_uac2 *uac2 = func_to_uac2(f: fn); |
1771 | u16 w_length = le16_to_cpu(cr->wLength); |
1772 | u16 w_index = le16_to_cpu(cr->wIndex); |
1773 | u16 w_value = le16_to_cpu(cr->wValue); |
1774 | u8 entity_id = (w_index >> 8) & 0xff; |
1775 | u8 control_selector = w_value >> 8; |
1776 | u8 clock_id = w_index >> 8; |
1777 | |
1778 | if ((entity_id == USB_IN_CLK_ID) || (entity_id == USB_OUT_CLK_ID)) { |
1779 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { |
1780 | dev_dbg(&agdev->gadget->dev, |
1781 | "control_selector UAC2_CS_CONTROL_SAM_FREQ, clock: %d\n" , clock_id); |
1782 | cdev->gadget->ep0->driver_data = fn; |
1783 | uac2->clock_id = clock_id; |
1784 | req->complete = uac2_cs_control_sam_freq; |
1785 | return w_length; |
1786 | } |
1787 | } else if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) || |
1788 | (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) { |
1789 | memcpy(&uac2->setup_cr, cr, sizeof(*cr)); |
1790 | req->context = agdev; |
1791 | req->complete = out_rq_cur_complete; |
1792 | |
1793 | return w_length; |
1794 | } else { |
1795 | dev_err(&agdev->gadget->dev, |
1796 | "%s:%d entity_id=%d control_selector=%d TODO!\n" , |
1797 | __func__, __LINE__, entity_id, control_selector); |
1798 | } |
1799 | return -EOPNOTSUPP; |
1800 | } |
1801 | |
1802 | static int |
1803 | setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr) |
1804 | { |
1805 | struct f_uac2 *uac2 = func_to_uac2(f: fn); |
1806 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1807 | u16 w_index = le16_to_cpu(cr->wIndex); |
1808 | u8 intf = w_index & 0xff; |
1809 | |
1810 | if (intf != uac2->ac_intf) { |
1811 | dev_err(&agdev->gadget->dev, |
1812 | "%s:%d Error!\n" , __func__, __LINE__); |
1813 | return -EOPNOTSUPP; |
1814 | } |
1815 | |
1816 | if (cr->bRequestType & USB_DIR_IN) |
1817 | return ac_rq_in(fn, cr); |
1818 | else if (cr->bRequest == UAC2_CS_CUR) |
1819 | return out_rq_cur(fn, cr); |
1820 | |
1821 | return -EOPNOTSUPP; |
1822 | } |
1823 | |
1824 | static int |
1825 | afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr) |
1826 | { |
1827 | struct usb_composite_dev *cdev = fn->config->cdev; |
1828 | struct g_audio *agdev = func_to_g_audio(f: fn); |
1829 | struct usb_request *req = cdev->req; |
1830 | u16 w_length = le16_to_cpu(cr->wLength); |
1831 | int value = -EOPNOTSUPP; |
1832 | |
1833 | /* Only Class specific requests are supposed to reach here */ |
1834 | if ((cr->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) |
1835 | return -EOPNOTSUPP; |
1836 | |
1837 | if ((cr->bRequestType & USB_RECIP_MASK) == USB_RECIP_INTERFACE) |
1838 | value = setup_rq_inf(fn, cr); |
1839 | else |
1840 | dev_err(&agdev->gadget->dev, "%s:%d Error!\n" , |
1841 | __func__, __LINE__); |
1842 | |
1843 | if (value >= 0) { |
1844 | req->length = value; |
1845 | req->zero = value < w_length; |
1846 | value = usb_ep_queue(ep: cdev->gadget->ep0, req, GFP_ATOMIC); |
1847 | if (value < 0) { |
1848 | dev_err(&agdev->gadget->dev, |
1849 | "%s:%d Error!\n" , __func__, __LINE__); |
1850 | req->status = 0; |
1851 | } |
1852 | } |
1853 | |
1854 | return value; |
1855 | } |
1856 | |
1857 | static inline struct f_uac2_opts *to_f_uac2_opts(struct config_item *item) |
1858 | { |
1859 | return container_of(to_config_group(item), struct f_uac2_opts, |
1860 | func_inst.group); |
1861 | } |
1862 | |
1863 | static void f_uac2_attr_release(struct config_item *item) |
1864 | { |
1865 | struct f_uac2_opts *opts = to_f_uac2_opts(item); |
1866 | |
1867 | usb_put_function_instance(fi: &opts->func_inst); |
1868 | } |
1869 | |
1870 | static struct configfs_item_operations f_uac2_item_ops = { |
1871 | .release = f_uac2_attr_release, |
1872 | }; |
1873 | |
1874 | #define uac2_kstrtou8 kstrtou8 |
1875 | #define uac2_kstrtou32 kstrtou32 |
1876 | #define uac2_kstrtos16 kstrtos16 |
1877 | #define uac2_kstrtobool(s, base, res) kstrtobool((s), (res)) |
1878 | |
1879 | static const char *u8_fmt = "%u\n" ; |
1880 | static const char *u32_fmt = "%u\n" ; |
1881 | static const char *s16_fmt = "%hd\n" ; |
1882 | static const char *bool_fmt = "%u\n" ; |
1883 | |
1884 | #define UAC2_ATTRIBUTE(type, name) \ |
1885 | static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ |
1886 | char *page) \ |
1887 | { \ |
1888 | struct f_uac2_opts *opts = to_f_uac2_opts(item); \ |
1889 | int result; \ |
1890 | \ |
1891 | mutex_lock(&opts->lock); \ |
1892 | result = sprintf(page, type##_fmt, opts->name); \ |
1893 | mutex_unlock(&opts->lock); \ |
1894 | \ |
1895 | return result; \ |
1896 | } \ |
1897 | \ |
1898 | static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ |
1899 | const char *page, size_t len) \ |
1900 | { \ |
1901 | struct f_uac2_opts *opts = to_f_uac2_opts(item); \ |
1902 | int ret; \ |
1903 | type num; \ |
1904 | \ |
1905 | mutex_lock(&opts->lock); \ |
1906 | if (opts->refcnt) { \ |
1907 | ret = -EBUSY; \ |
1908 | goto end; \ |
1909 | } \ |
1910 | \ |
1911 | ret = uac2_kstrto##type(page, 0, &num); \ |
1912 | if (ret) \ |
1913 | goto end; \ |
1914 | \ |
1915 | opts->name = num; \ |
1916 | ret = len; \ |
1917 | \ |
1918 | end: \ |
1919 | mutex_unlock(&opts->lock); \ |
1920 | return ret; \ |
1921 | } \ |
1922 | \ |
1923 | CONFIGFS_ATTR(f_uac2_opts_, name) |
1924 | |
1925 | #define UAC2_ATTRIBUTE_SYNC(name) \ |
1926 | static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ |
1927 | char *page) \ |
1928 | { \ |
1929 | struct f_uac2_opts *opts = to_f_uac2_opts(item); \ |
1930 | int result; \ |
1931 | char *str; \ |
1932 | \ |
1933 | mutex_lock(&opts->lock); \ |
1934 | switch (opts->name) { \ |
1935 | case USB_ENDPOINT_SYNC_ASYNC: \ |
1936 | str = "async"; \ |
1937 | break; \ |
1938 | case USB_ENDPOINT_SYNC_ADAPTIVE: \ |
1939 | str = "adaptive"; \ |
1940 | break; \ |
1941 | default: \ |
1942 | str = "unknown"; \ |
1943 | break; \ |
1944 | } \ |
1945 | result = sprintf(page, "%s\n", str); \ |
1946 | mutex_unlock(&opts->lock); \ |
1947 | \ |
1948 | return result; \ |
1949 | } \ |
1950 | \ |
1951 | static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ |
1952 | const char *page, size_t len) \ |
1953 | { \ |
1954 | struct f_uac2_opts *opts = to_f_uac2_opts(item); \ |
1955 | int ret = 0; \ |
1956 | \ |
1957 | mutex_lock(&opts->lock); \ |
1958 | if (opts->refcnt) { \ |
1959 | ret = -EBUSY; \ |
1960 | goto end; \ |
1961 | } \ |
1962 | \ |
1963 | if (!strncmp(page, "async", 5)) \ |
1964 | opts->name = USB_ENDPOINT_SYNC_ASYNC; \ |
1965 | else if (!strncmp(page, "adaptive", 8)) \ |
1966 | opts->name = USB_ENDPOINT_SYNC_ADAPTIVE; \ |
1967 | else { \ |
1968 | ret = -EINVAL; \ |
1969 | goto end; \ |
1970 | } \ |
1971 | \ |
1972 | ret = len; \ |
1973 | \ |
1974 | end: \ |
1975 | mutex_unlock(&opts->lock); \ |
1976 | return ret; \ |
1977 | } \ |
1978 | \ |
1979 | CONFIGFS_ATTR(f_uac2_opts_, name) |
1980 | |
1981 | #define UAC2_RATE_ATTRIBUTE(name) \ |
1982 | static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ |
1983 | char *page) \ |
1984 | { \ |
1985 | struct f_uac2_opts *opts = to_f_uac2_opts(item); \ |
1986 | int result = 0; \ |
1987 | int i; \ |
1988 | \ |
1989 | mutex_lock(&opts->lock); \ |
1990 | page[0] = '\0'; \ |
1991 | for (i = 0; i < UAC_MAX_RATES; i++) { \ |
1992 | if (opts->name##s[i] == 0) \ |
1993 | break; \ |
1994 | result += sprintf(page + strlen(page), "%u,", \ |
1995 | opts->name##s[i]); \ |
1996 | } \ |
1997 | if (strlen(page) > 0) \ |
1998 | page[strlen(page) - 1] = '\n'; \ |
1999 | mutex_unlock(&opts->lock); \ |
2000 | \ |
2001 | return result; \ |
2002 | } \ |
2003 | \ |
2004 | static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ |
2005 | const char *page, size_t len) \ |
2006 | { \ |
2007 | struct f_uac2_opts *opts = to_f_uac2_opts(item); \ |
2008 | char *split_page = NULL; \ |
2009 | int ret = -EINVAL; \ |
2010 | char *token; \ |
2011 | u32 num; \ |
2012 | int i; \ |
2013 | \ |
2014 | mutex_lock(&opts->lock); \ |
2015 | if (opts->refcnt) { \ |
2016 | ret = -EBUSY; \ |
2017 | goto end; \ |
2018 | } \ |
2019 | \ |
2020 | i = 0; \ |
2021 | memset(opts->name##s, 0x00, sizeof(opts->name##s)); \ |
2022 | split_page = kstrdup(page, GFP_KERNEL); \ |
2023 | while ((token = strsep(&split_page, ",")) != NULL) { \ |
2024 | ret = kstrtou32(token, 0, &num); \ |
2025 | if (ret) \ |
2026 | goto end; \ |
2027 | \ |
2028 | opts->name##s[i++] = num; \ |
2029 | ret = len; \ |
2030 | }; \ |
2031 | \ |
2032 | end: \ |
2033 | kfree(split_page); \ |
2034 | mutex_unlock(&opts->lock); \ |
2035 | return ret; \ |
2036 | } \ |
2037 | \ |
2038 | CONFIGFS_ATTR(f_uac2_opts_, name) |
2039 | |
2040 | #define UAC2_ATTRIBUTE_STRING(name) \ |
2041 | static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ |
2042 | char *page) \ |
2043 | { \ |
2044 | struct f_uac2_opts *opts = to_f_uac2_opts(item); \ |
2045 | int result; \ |
2046 | \ |
2047 | mutex_lock(&opts->lock); \ |
2048 | result = scnprintf(page, sizeof(opts->name), "%s", opts->name); \ |
2049 | mutex_unlock(&opts->lock); \ |
2050 | \ |
2051 | return result; \ |
2052 | } \ |
2053 | \ |
2054 | static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ |
2055 | const char *page, size_t len) \ |
2056 | { \ |
2057 | struct f_uac2_opts *opts = to_f_uac2_opts(item); \ |
2058 | int ret = 0; \ |
2059 | \ |
2060 | mutex_lock(&opts->lock); \ |
2061 | if (opts->refcnt) { \ |
2062 | ret = -EBUSY; \ |
2063 | goto end; \ |
2064 | } \ |
2065 | \ |
2066 | ret = scnprintf(opts->name, min(sizeof(opts->name), len), \ |
2067 | "%s", page); \ |
2068 | \ |
2069 | end: \ |
2070 | mutex_unlock(&opts->lock); \ |
2071 | return ret; \ |
2072 | } \ |
2073 | \ |
2074 | CONFIGFS_ATTR(f_uac2_opts_, name) |
2075 | |
2076 | UAC2_ATTRIBUTE(u32, p_chmask); |
2077 | UAC2_RATE_ATTRIBUTE(p_srate); |
2078 | UAC2_ATTRIBUTE(u32, p_ssize); |
2079 | UAC2_ATTRIBUTE(u8, p_hs_bint); |
2080 | UAC2_ATTRIBUTE(u32, c_chmask); |
2081 | UAC2_RATE_ATTRIBUTE(c_srate); |
2082 | UAC2_ATTRIBUTE_SYNC(c_sync); |
2083 | UAC2_ATTRIBUTE(u32, c_ssize); |
2084 | UAC2_ATTRIBUTE(u8, c_hs_bint); |
2085 | UAC2_ATTRIBUTE(u32, req_number); |
2086 | |
2087 | UAC2_ATTRIBUTE(bool, p_mute_present); |
2088 | UAC2_ATTRIBUTE(bool, p_volume_present); |
2089 | UAC2_ATTRIBUTE(s16, p_volume_min); |
2090 | UAC2_ATTRIBUTE(s16, p_volume_max); |
2091 | UAC2_ATTRIBUTE(s16, p_volume_res); |
2092 | |
2093 | UAC2_ATTRIBUTE(bool, c_mute_present); |
2094 | UAC2_ATTRIBUTE(bool, c_volume_present); |
2095 | UAC2_ATTRIBUTE(s16, c_volume_min); |
2096 | UAC2_ATTRIBUTE(s16, c_volume_max); |
2097 | UAC2_ATTRIBUTE(s16, c_volume_res); |
2098 | UAC2_ATTRIBUTE(u32, fb_max); |
2099 | UAC2_ATTRIBUTE_STRING(function_name); |
2100 | |
2101 | UAC2_ATTRIBUTE(s16, p_terminal_type); |
2102 | UAC2_ATTRIBUTE(s16, c_terminal_type); |
2103 | |
2104 | static struct configfs_attribute *f_uac2_attrs[] = { |
2105 | &f_uac2_opts_attr_p_chmask, |
2106 | &f_uac2_opts_attr_p_srate, |
2107 | &f_uac2_opts_attr_p_ssize, |
2108 | &f_uac2_opts_attr_p_hs_bint, |
2109 | &f_uac2_opts_attr_c_chmask, |
2110 | &f_uac2_opts_attr_c_srate, |
2111 | &f_uac2_opts_attr_c_ssize, |
2112 | &f_uac2_opts_attr_c_hs_bint, |
2113 | &f_uac2_opts_attr_c_sync, |
2114 | &f_uac2_opts_attr_req_number, |
2115 | &f_uac2_opts_attr_fb_max, |
2116 | |
2117 | &f_uac2_opts_attr_p_mute_present, |
2118 | &f_uac2_opts_attr_p_volume_present, |
2119 | &f_uac2_opts_attr_p_volume_min, |
2120 | &f_uac2_opts_attr_p_volume_max, |
2121 | &f_uac2_opts_attr_p_volume_res, |
2122 | |
2123 | &f_uac2_opts_attr_c_mute_present, |
2124 | &f_uac2_opts_attr_c_volume_present, |
2125 | &f_uac2_opts_attr_c_volume_min, |
2126 | &f_uac2_opts_attr_c_volume_max, |
2127 | &f_uac2_opts_attr_c_volume_res, |
2128 | |
2129 | &f_uac2_opts_attr_function_name, |
2130 | |
2131 | &f_uac2_opts_attr_p_terminal_type, |
2132 | &f_uac2_opts_attr_c_terminal_type, |
2133 | |
2134 | NULL, |
2135 | }; |
2136 | |
2137 | static const struct config_item_type f_uac2_func_type = { |
2138 | .ct_item_ops = &f_uac2_item_ops, |
2139 | .ct_attrs = f_uac2_attrs, |
2140 | .ct_owner = THIS_MODULE, |
2141 | }; |
2142 | |
2143 | static void afunc_free_inst(struct usb_function_instance *f) |
2144 | { |
2145 | struct f_uac2_opts *opts; |
2146 | |
2147 | opts = container_of(f, struct f_uac2_opts, func_inst); |
2148 | kfree(objp: opts); |
2149 | } |
2150 | |
2151 | static struct usb_function_instance *afunc_alloc_inst(void) |
2152 | { |
2153 | struct f_uac2_opts *opts; |
2154 | |
2155 | opts = kzalloc(size: sizeof(*opts), GFP_KERNEL); |
2156 | if (!opts) |
2157 | return ERR_PTR(error: -ENOMEM); |
2158 | |
2159 | mutex_init(&opts->lock); |
2160 | opts->func_inst.free_func_inst = afunc_free_inst; |
2161 | |
2162 | config_group_init_type_name(group: &opts->func_inst.group, name: "" , |
2163 | type: &f_uac2_func_type); |
2164 | |
2165 | opts->p_chmask = UAC2_DEF_PCHMASK; |
2166 | opts->p_srates[0] = UAC2_DEF_PSRATE; |
2167 | opts->p_ssize = UAC2_DEF_PSSIZE; |
2168 | opts->p_hs_bint = UAC2_DEF_PHSBINT; |
2169 | opts->c_chmask = UAC2_DEF_CCHMASK; |
2170 | opts->c_srates[0] = UAC2_DEF_CSRATE; |
2171 | opts->c_ssize = UAC2_DEF_CSSIZE; |
2172 | opts->c_hs_bint = UAC2_DEF_CHSBINT; |
2173 | opts->c_sync = UAC2_DEF_CSYNC; |
2174 | |
2175 | opts->p_mute_present = UAC2_DEF_MUTE_PRESENT; |
2176 | opts->p_volume_present = UAC2_DEF_VOLUME_PRESENT; |
2177 | opts->p_volume_min = UAC2_DEF_MIN_DB; |
2178 | opts->p_volume_max = UAC2_DEF_MAX_DB; |
2179 | opts->p_volume_res = UAC2_DEF_RES_DB; |
2180 | |
2181 | opts->c_mute_present = UAC2_DEF_MUTE_PRESENT; |
2182 | opts->c_volume_present = UAC2_DEF_VOLUME_PRESENT; |
2183 | opts->c_volume_min = UAC2_DEF_MIN_DB; |
2184 | opts->c_volume_max = UAC2_DEF_MAX_DB; |
2185 | opts->c_volume_res = UAC2_DEF_RES_DB; |
2186 | |
2187 | opts->req_number = UAC2_DEF_REQ_NUM; |
2188 | opts->fb_max = FBACK_FAST_MAX; |
2189 | |
2190 | scnprintf(buf: opts->function_name, size: sizeof(opts->function_name), fmt: "Source/Sink" ); |
2191 | |
2192 | opts->p_terminal_type = UAC2_DEF_P_TERM_TYPE; |
2193 | opts->c_terminal_type = UAC2_DEF_C_TERM_TYPE; |
2194 | |
2195 | return &opts->func_inst; |
2196 | } |
2197 | |
2198 | static void afunc_free(struct usb_function *f) |
2199 | { |
2200 | struct g_audio *agdev; |
2201 | struct f_uac2_opts *opts; |
2202 | |
2203 | agdev = func_to_g_audio(f); |
2204 | opts = container_of(f->fi, struct f_uac2_opts, func_inst); |
2205 | kfree(objp: agdev); |
2206 | mutex_lock(&opts->lock); |
2207 | --opts->refcnt; |
2208 | mutex_unlock(lock: &opts->lock); |
2209 | } |
2210 | |
2211 | static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) |
2212 | { |
2213 | struct g_audio *agdev = func_to_g_audio(f); |
2214 | |
2215 | g_audio_cleanup(g_audio: agdev); |
2216 | usb_free_all_descriptors(f); |
2217 | |
2218 | agdev->gadget = NULL; |
2219 | |
2220 | kfree(objp: out_feature_unit_desc); |
2221 | out_feature_unit_desc = NULL; |
2222 | kfree(objp: in_feature_unit_desc); |
2223 | in_feature_unit_desc = NULL; |
2224 | } |
2225 | |
2226 | static struct usb_function *afunc_alloc(struct usb_function_instance *fi) |
2227 | { |
2228 | struct f_uac2 *uac2; |
2229 | struct f_uac2_opts *opts; |
2230 | |
2231 | uac2 = kzalloc(size: sizeof(*uac2), GFP_KERNEL); |
2232 | if (uac2 == NULL) |
2233 | return ERR_PTR(error: -ENOMEM); |
2234 | |
2235 | opts = container_of(fi, struct f_uac2_opts, func_inst); |
2236 | mutex_lock(&opts->lock); |
2237 | ++opts->refcnt; |
2238 | mutex_unlock(lock: &opts->lock); |
2239 | |
2240 | uac2->g_audio.func.name = "uac2_func" ; |
2241 | uac2->g_audio.func.bind = afunc_bind; |
2242 | uac2->g_audio.func.unbind = afunc_unbind; |
2243 | uac2->g_audio.func.set_alt = afunc_set_alt; |
2244 | uac2->g_audio.func.get_alt = afunc_get_alt; |
2245 | uac2->g_audio.func.disable = afunc_disable; |
2246 | uac2->g_audio.func.suspend = afunc_suspend; |
2247 | uac2->g_audio.func.setup = afunc_setup; |
2248 | uac2->g_audio.func.free_func = afunc_free; |
2249 | |
2250 | return &uac2->g_audio.func; |
2251 | } |
2252 | |
2253 | DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc); |
2254 | MODULE_LICENSE("GPL" ); |
2255 | MODULE_AUTHOR("Yadwinder Singh" ); |
2256 | MODULE_AUTHOR("Jaswinder Singh" ); |
2257 | MODULE_AUTHOR("Ruslan Bilovol" ); |
2258 | |