]>
Commit | Line | Data |
---|---|---|
5fd54ace | 1 | // SPDX-License-Identifier: GPL-2.0+ |
c6994e6f BW |
2 | /* |
3 | * audio.c -- Audio gadget driver | |
4 | * | |
5 | * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> | |
6 | * Copyright (C) 2008 Analog Devices, Inc | |
c6994e6f BW |
7 | */ |
8 | ||
9 | /* #define VERBOSE_DEBUG */ | |
10 | ||
11 | #include <linux/kernel.h> | |
721e2e91 | 12 | #include <linux/module.h> |
7d16e8d3 | 13 | #include <linux/usb/composite.h> |
c6994e6f | 14 | |
c6994e6f | 15 | #define DRIVER_DESC "Linux USB Audio Gadget" |
132fcb46 | 16 | #define DRIVER_VERSION "Feb 2, 2012" |
c6994e6f | 17 | |
7d16e8d3 | 18 | USB_GADGET_COMPOSITE_OPTIONS(); |
c6994e6f | 19 | |
0591bc23 | 20 | #ifndef CONFIG_GADGET_UAC1 |
065a107c AP |
21 | #include "u_uac2.h" |
22 | ||
ad94ac0c | 23 | /* Playback(USB-IN) Default Stereo - Fl/Fr */ |
065a107c | 24 | static int p_chmask = UAC2_DEF_PCHMASK; |
ad94ac0c AP |
25 | module_param(p_chmask, uint, S_IRUGO); |
26 | MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); | |
27 | ||
28 | /* Playback Default 48 KHz */ | |
065a107c | 29 | static int p_srate = UAC2_DEF_PSRATE; |
ad94ac0c AP |
30 | module_param(p_srate, uint, S_IRUGO); |
31 | MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); | |
32 | ||
33 | /* Playback Default 16bits/sample */ | |
065a107c | 34 | static int p_ssize = UAC2_DEF_PSSIZE; |
ad94ac0c AP |
35 | module_param(p_ssize, uint, S_IRUGO); |
36 | MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); | |
37 | ||
38 | /* Capture(USB-OUT) Default Stereo - Fl/Fr */ | |
065a107c | 39 | static int c_chmask = UAC2_DEF_CCHMASK; |
ad94ac0c AP |
40 | module_param(c_chmask, uint, S_IRUGO); |
41 | MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); | |
42 | ||
43 | /* Capture Default 64 KHz */ | |
065a107c | 44 | static int c_srate = UAC2_DEF_CSRATE; |
ad94ac0c AP |
45 | module_param(c_srate, uint, S_IRUGO); |
46 | MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); | |
47 | ||
48 | /* Capture Default 16bits/sample */ | |
065a107c | 49 | static int c_ssize = UAC2_DEF_CSSIZE; |
ad94ac0c AP |
50 | module_param(c_ssize, uint, S_IRUGO); |
51 | MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); | |
0d992dec | 52 | #else |
0591bc23 RB |
53 | #ifndef CONFIG_GADGET_UAC1_LEGACY |
54 | #include "u_uac1.h" | |
55 | ||
56 | /* Playback(USB-IN) Default Stereo - Fl/Fr */ | |
57 | static int p_chmask = UAC1_DEF_PCHMASK; | |
58 | module_param(p_chmask, uint, S_IRUGO); | |
59 | MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); | |
60 | ||
61 | /* Playback Default 48 KHz */ | |
62 | static int p_srate = UAC1_DEF_PSRATE; | |
63 | module_param(p_srate, uint, S_IRUGO); | |
64 | MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); | |
65 | ||
66 | /* Playback Default 16bits/sample */ | |
67 | static int p_ssize = UAC1_DEF_PSSIZE; | |
68 | module_param(p_ssize, uint, S_IRUGO); | |
69 | MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); | |
70 | ||
71 | /* Capture(USB-OUT) Default Stereo - Fl/Fr */ | |
72 | static int c_chmask = UAC1_DEF_CCHMASK; | |
73 | module_param(c_chmask, uint, S_IRUGO); | |
74 | MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); | |
75 | ||
76 | /* Capture Default 48 KHz */ | |
77 | static int c_srate = UAC1_DEF_CSRATE; | |
78 | module_param(c_srate, uint, S_IRUGO); | |
79 | MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); | |
80 | ||
81 | /* Capture Default 16bits/sample */ | |
82 | static int c_ssize = UAC1_DEF_CSSIZE; | |
83 | module_param(c_ssize, uint, S_IRUGO); | |
84 | MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); | |
85 | #else /* CONFIG_GADGET_UAC1_LEGACY */ | |
d355339e | 86 | #include "u_uac1_legacy.h" |
0d992dec AP |
87 | |
88 | static char *fn_play = FILE_PCM_PLAYBACK; | |
89 | module_param(fn_play, charp, S_IRUGO); | |
90 | MODULE_PARM_DESC(fn_play, "Playback PCM device file name"); | |
91 | ||
92 | static char *fn_cap = FILE_PCM_CAPTURE; | |
93 | module_param(fn_cap, charp, S_IRUGO); | |
94 | MODULE_PARM_DESC(fn_cap, "Capture PCM device file name"); | |
95 | ||
96 | static char *fn_cntl = FILE_CONTROL; | |
97 | module_param(fn_cntl, charp, S_IRUGO); | |
98 | MODULE_PARM_DESC(fn_cntl, "Control device file name"); | |
99 | ||
bcec9784 | 100 | static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; |
0d992dec AP |
101 | module_param(req_buf_size, int, S_IRUGO); |
102 | MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size"); | |
103 | ||
bcec9784 | 104 | static int req_count = UAC1_REQ_COUNT; |
0d992dec AP |
105 | module_param(req_count, int, S_IRUGO); |
106 | MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count"); | |
107 | ||
bcec9784 | 108 | static int audio_buf_size = UAC1_AUDIO_BUF_SIZE; |
0d992dec AP |
109 | module_param(audio_buf_size, int, S_IRUGO); |
110 | MODULE_PARM_DESC(audio_buf_size, "Audio buffer size"); | |
0591bc23 | 111 | #endif /* CONFIG_GADGET_UAC1_LEGACY */ |
ad94ac0c AP |
112 | #endif |
113 | ||
d747a916 JB |
114 | /* string IDs are assigned dynamically */ |
115 | ||
d747a916 | 116 | static struct usb_string strings_dev[] = { |
cc2683c3 | 117 | [USB_GADGET_MANUFACTURER_IDX].s = "", |
276e2e4f SAS |
118 | [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, |
119 | [USB_GADGET_SERIAL_IDX].s = "", | |
d747a916 JB |
120 | { } /* end of list */ |
121 | }; | |
122 | ||
123 | static struct usb_gadget_strings stringtab_dev = { | |
124 | .language = 0x0409, /* en-us */ | |
125 | .strings = strings_dev, | |
126 | }; | |
127 | ||
128 | static struct usb_gadget_strings *audio_strings[] = { | |
129 | &stringtab_dev, | |
130 | NULL, | |
131 | }; | |
132 | ||
0591bc23 | 133 | #ifndef CONFIG_GADGET_UAC1 |
ad94ac0c AP |
134 | static struct usb_function_instance *fi_uac2; |
135 | static struct usb_function *f_uac2; | |
0d992dec AP |
136 | #else |
137 | static struct usb_function_instance *fi_uac1; | |
138 | static struct usb_function *f_uac1; | |
ad94ac0c AP |
139 | #endif |
140 | ||
c6994e6f BW |
141 | /*-------------------------------------------------------------------------*/ |
142 | ||
143 | /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! | |
144 | * Instead: allocate your own, using normal USB-IF procedures. | |
145 | */ | |
146 | ||
05cbc2d5 GKH |
147 | /* Thanks to Linux Foundation for donating this product ID. */ |
148 | #define AUDIO_VENDOR_NUM 0x1d6b /* Linux Foundation */ | |
149 | #define AUDIO_PRODUCT_NUM 0x0101 /* Linux-USB Audio Gadget */ | |
c6994e6f BW |
150 | |
151 | /*-------------------------------------------------------------------------*/ | |
152 | ||
153 | static struct usb_device_descriptor device_desc = { | |
154 | .bLength = sizeof device_desc, | |
155 | .bDescriptorType = USB_DT_DEVICE, | |
156 | ||
0aecfc1b | 157 | /* .bcdUSB = DYNAMIC */ |
c6994e6f | 158 | |
d355339e | 159 | #ifdef CONFIG_GADGET_UAC1_LEGACY |
c6994e6f BW |
160 | .bDeviceClass = USB_CLASS_PER_INTERFACE, |
161 | .bDeviceSubClass = 0, | |
162 | .bDeviceProtocol = 0, | |
132fcb46 JB |
163 | #else |
164 | .bDeviceClass = USB_CLASS_MISC, | |
165 | .bDeviceSubClass = 0x02, | |
166 | .bDeviceProtocol = 0x01, | |
167 | #endif | |
c6994e6f BW |
168 | /* .bMaxPacketSize0 = f(hardware) */ |
169 | ||
170 | /* Vendor and product id defaults change according to what configs | |
171 | * we support. (As does bNumConfigurations.) These values can | |
172 | * also be overridden by module parameters. | |
173 | */ | |
b8464bcf VT |
174 | .idVendor = cpu_to_le16(AUDIO_VENDOR_NUM), |
175 | .idProduct = cpu_to_le16(AUDIO_PRODUCT_NUM), | |
c6994e6f BW |
176 | /* .bcdDevice = f(hardware) */ |
177 | /* .iManufacturer = DYNAMIC */ | |
178 | /* .iProduct = DYNAMIC */ | |
179 | /* NO SERIAL NUMBER */ | |
180 | .bNumConfigurations = 1, | |
181 | }; | |
182 | ||
56023ce0 | 183 | static const struct usb_descriptor_header *otg_desc[2]; |
c6994e6f BW |
184 | |
185 | /*-------------------------------------------------------------------------*/ | |
186 | ||
c94e289f | 187 | static int audio_do_config(struct usb_configuration *c) |
c6994e6f | 188 | { |
ad94ac0c | 189 | int status; |
ad94ac0c | 190 | |
c6994e6f BW |
191 | /* FIXME alloc iConfiguration string, set it in c->strings */ |
192 | ||
193 | if (gadget_is_otg(c->cdev->gadget)) { | |
194 | c->descriptors = otg_desc; | |
195 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | |
196 | } | |
197 | ||
0591bc23 | 198 | #ifdef CONFIG_GADGET_UAC1 |
0d992dec AP |
199 | f_uac1 = usb_get_function(fi_uac1); |
200 | if (IS_ERR(f_uac1)) { | |
201 | status = PTR_ERR(f_uac1); | |
202 | return status; | |
203 | } | |
204 | ||
205 | status = usb_add_function(c, f_uac1); | |
206 | if (status < 0) { | |
207 | usb_put_function(f_uac1); | |
208 | return status; | |
209 | } | |
ad94ac0c AP |
210 | #else |
211 | f_uac2 = usb_get_function(fi_uac2); | |
212 | if (IS_ERR(f_uac2)) { | |
213 | status = PTR_ERR(f_uac2); | |
214 | return status; | |
215 | } | |
216 | ||
217 | status = usb_add_function(c, f_uac2); | |
218 | if (status < 0) { | |
219 | usb_put_function(f_uac2); | |
220 | return status; | |
221 | } | |
222 | #endif | |
c6994e6f BW |
223 | |
224 | return 0; | |
225 | } | |
226 | ||
227 | static struct usb_configuration audio_config_driver = { | |
228 | .label = DRIVER_DESC, | |
c6994e6f BW |
229 | .bConfigurationValue = 1, |
230 | /* .iConfiguration = DYNAMIC */ | |
231 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | |
232 | }; | |
233 | ||
234 | /*-------------------------------------------------------------------------*/ | |
235 | ||
c94e289f | 236 | static int audio_bind(struct usb_composite_dev *cdev) |
c6994e6f | 237 | { |
0591bc23 | 238 | #ifndef CONFIG_GADGET_UAC1 |
ad94ac0c | 239 | struct f_uac2_opts *uac2_opts; |
0591bc23 RB |
240 | #else |
241 | #ifndef CONFIG_GADGET_UAC1_LEGACY | |
242 | struct f_uac1_opts *uac1_opts; | |
0d992dec | 243 | #else |
d355339e | 244 | struct f_uac1_legacy_opts *uac1_opts; |
0591bc23 | 245 | #endif |
ad94ac0c | 246 | #endif |
c6994e6f BW |
247 | int status; |
248 | ||
0591bc23 | 249 | #ifndef CONFIG_GADGET_UAC1 |
ad94ac0c AP |
250 | fi_uac2 = usb_get_function_instance("uac2"); |
251 | if (IS_ERR(fi_uac2)) | |
252 | return PTR_ERR(fi_uac2); | |
0591bc23 RB |
253 | #else |
254 | #ifndef CONFIG_GADGET_UAC1_LEGACY | |
255 | fi_uac1 = usb_get_function_instance("uac1"); | |
0d992dec | 256 | #else |
d355339e | 257 | fi_uac1 = usb_get_function_instance("uac1_legacy"); |
0591bc23 | 258 | #endif |
0d992dec AP |
259 | if (IS_ERR(fi_uac1)) |
260 | return PTR_ERR(fi_uac1); | |
ad94ac0c AP |
261 | #endif |
262 | ||
0591bc23 | 263 | #ifndef CONFIG_GADGET_UAC1 |
ad94ac0c AP |
264 | uac2_opts = container_of(fi_uac2, struct f_uac2_opts, func_inst); |
265 | uac2_opts->p_chmask = p_chmask; | |
266 | uac2_opts->p_srate = p_srate; | |
267 | uac2_opts->p_ssize = p_ssize; | |
268 | uac2_opts->c_chmask = c_chmask; | |
269 | uac2_opts->c_srate = c_srate; | |
270 | uac2_opts->c_ssize = c_ssize; | |
e92b9d44 | 271 | uac2_opts->req_number = UAC2_DEF_REQ_NUM; |
0d992dec | 272 | #else |
0591bc23 RB |
273 | #ifndef CONFIG_GADGET_UAC1_LEGACY |
274 | uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst); | |
275 | uac1_opts->p_chmask = p_chmask; | |
276 | uac1_opts->p_srate = p_srate; | |
277 | uac1_opts->p_ssize = p_ssize; | |
278 | uac1_opts->c_chmask = c_chmask; | |
279 | uac1_opts->c_srate = c_srate; | |
280 | uac1_opts->c_ssize = c_ssize; | |
281 | uac1_opts->req_number = UAC1_DEF_REQ_NUM; | |
282 | #else /* CONFIG_GADGET_UAC1_LEGACY */ | |
d355339e | 283 | uac1_opts = container_of(fi_uac1, struct f_uac1_legacy_opts, func_inst); |
0d992dec AP |
284 | uac1_opts->fn_play = fn_play; |
285 | uac1_opts->fn_cap = fn_cap; | |
286 | uac1_opts->fn_cntl = fn_cntl; | |
287 | uac1_opts->req_buf_size = req_buf_size; | |
288 | uac1_opts->req_count = req_count; | |
289 | uac1_opts->audio_buf_size = audio_buf_size; | |
0591bc23 | 290 | #endif /* CONFIG_GADGET_UAC1_LEGACY */ |
ad94ac0c AP |
291 | #endif |
292 | ||
e1f15ccb | 293 | status = usb_string_ids_tab(cdev, strings_dev); |
c6994e6f BW |
294 | if (status < 0) |
295 | goto fail; | |
276e2e4f SAS |
296 | device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; |
297 | device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; | |
c6994e6f | 298 | |
56023ce0 LJ |
299 | if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) { |
300 | struct usb_descriptor_header *usb_desc; | |
301 | ||
302 | usb_desc = usb_otg_descriptor_alloc(cdev->gadget); | |
19b94c1f CJ |
303 | if (!usb_desc) { |
304 | status = -ENOMEM; | |
56023ce0 | 305 | goto fail; |
19b94c1f | 306 | } |
56023ce0 LJ |
307 | usb_otg_descriptor_init(cdev->gadget, usb_desc); |
308 | otg_desc[0] = usb_desc; | |
309 | otg_desc[1] = NULL; | |
310 | } | |
311 | ||
c9bfff9c | 312 | status = usb_add_config(cdev, &audio_config_driver, audio_do_config); |
c6994e6f | 313 | if (status < 0) |
56023ce0 | 314 | goto fail_otg_desc; |
7d16e8d3 | 315 | usb_composite_overwrite_options(cdev, &coverwrite); |
c6994e6f BW |
316 | |
317 | INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION); | |
318 | return 0; | |
319 | ||
56023ce0 LJ |
320 | fail_otg_desc: |
321 | kfree(otg_desc[0]); | |
322 | otg_desc[0] = NULL; | |
c6994e6f | 323 | fail: |
0591bc23 | 324 | #ifndef CONFIG_GADGET_UAC1 |
ad94ac0c | 325 | usb_put_function_instance(fi_uac2); |
0d992dec AP |
326 | #else |
327 | usb_put_function_instance(fi_uac1); | |
ad94ac0c | 328 | #endif |
c6994e6f BW |
329 | return status; |
330 | } | |
331 | ||
c94e289f | 332 | static int audio_unbind(struct usb_composite_dev *cdev) |
c6994e6f | 333 | { |
0591bc23 | 334 | #ifdef CONFIG_GADGET_UAC1 |
0d992dec AP |
335 | if (!IS_ERR_OR_NULL(f_uac1)) |
336 | usb_put_function(f_uac1); | |
337 | if (!IS_ERR_OR_NULL(fi_uac1)) | |
338 | usb_put_function_instance(fi_uac1); | |
ad94ac0c AP |
339 | #else |
340 | if (!IS_ERR_OR_NULL(f_uac2)) | |
341 | usb_put_function(f_uac2); | |
342 | if (!IS_ERR_OR_NULL(fi_uac2)) | |
343 | usb_put_function_instance(fi_uac2); | |
132fcb46 | 344 | #endif |
56023ce0 LJ |
345 | kfree(otg_desc[0]); |
346 | otg_desc[0] = NULL; | |
347 | ||
c6994e6f BW |
348 | return 0; |
349 | } | |
350 | ||
c94e289f | 351 | static struct usb_composite_driver audio_driver = { |
c6994e6f BW |
352 | .name = "g_audio", |
353 | .dev = &device_desc, | |
354 | .strings = audio_strings, | |
35a0e0bf | 355 | .max_speed = USB_SPEED_HIGH, |
03e42bd5 | 356 | .bind = audio_bind, |
c94e289f | 357 | .unbind = audio_unbind, |
c6994e6f BW |
358 | }; |
359 | ||
909346a8 | 360 | module_usb_composite_driver(audio_driver); |
c6994e6f BW |
361 | |
362 | MODULE_DESCRIPTION(DRIVER_DESC); | |
363 | MODULE_AUTHOR("Bryan Wu <cooloney@kernel.org>"); | |
364 | MODULE_LICENSE("GPL"); | |
365 |