Merge branch 'sched/warnings' into sched/core, to pick up WARN_ON_ONCE() conversion...
[linux-block.git] / sound / usb / bcd2000 / bcd2000.c
CommitLineData
c942fddf 1// SPDX-License-Identifier: GPL-2.0-or-later
b47a2229
MK
2/*
3 * Behringer BCD2000 driver
4 *
5 * Copyright (C) 2014 Mario Kicherer (dev@kicherer.org)
b47a2229
MK
6 */
7
8#include <linux/kernel.h>
9#include <linux/errno.h>
10#include <linux/init.h>
11#include <linux/slab.h>
12#include <linux/module.h>
13#include <linux/bitmap.h>
14#include <linux/usb.h>
15#include <linux/usb/audio.h>
16#include <sound/core.h>
17#include <sound/initval.h>
18#include <sound/rawmidi.h>
19
20#define PREFIX "snd-bcd2000: "
21#define BUFSIZE 64
22
5e055ea2 23static const struct usb_device_id id_table[] = {
b47a2229
MK
24 { USB_DEVICE(0x1397, 0x00bd) },
25 { },
26};
27
71075c42 28static const unsigned char device_cmd_prefix[] = {0x03, 0x00};
b47a2229 29
71075c42 30static const unsigned char bcd2000_init_sequence[] = {
b47a2229
MK
31 0x07, 0x00, 0x00, 0x00, 0x78, 0x48, 0x1c, 0x81,
32 0xc4, 0x00, 0x00, 0x00, 0x5e, 0x53, 0x4a, 0xf7,
33 0x18, 0xfa, 0x11, 0xff, 0x6c, 0xf3, 0x90, 0xff,
34 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
35 0x18, 0xfa, 0x11, 0xff, 0x14, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0xf2, 0x34, 0x4a, 0xf7,
37 0x18, 0xfa, 0x11, 0xff
38};
39
40struct bcd2000 {
41 struct usb_device *dev;
42 struct snd_card *card;
43 struct usb_interface *intf;
44 int card_index;
45
46 int midi_out_active;
47 struct snd_rawmidi *rmidi;
48 struct snd_rawmidi_substream *midi_receive_substream;
49 struct snd_rawmidi_substream *midi_out_substream;
50
51 unsigned char midi_in_buf[BUFSIZE];
52 unsigned char midi_out_buf[BUFSIZE];
53
54 struct urb *midi_out_urb;
55 struct urb *midi_in_urb;
56
57 struct usb_anchor anchor;
58};
59
60static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
61static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
62
63static DEFINE_MUTEX(devices_mutex);
574d69c2 64static DECLARE_BITMAP(devices_used, SNDRV_CARDS);
b47a2229
MK
65static struct usb_driver bcd2000_driver;
66
67#ifdef CONFIG_SND_DEBUG
68static void bcd2000_dump_buffer(const char *prefix, const char *buf, int len)
69{
70 print_hex_dump(KERN_DEBUG, prefix,
71 DUMP_PREFIX_NONE, 16, 1,
72 buf, len, false);
73}
74#else
75static void bcd2000_dump_buffer(const char *prefix, const char *buf, int len) {}
76#endif
77
78static int bcd2000_midi_input_open(struct snd_rawmidi_substream *substream)
79{
80 return 0;
81}
82
83static int bcd2000_midi_input_close(struct snd_rawmidi_substream *substream)
84{
85 return 0;
86}
87
88/* (de)register midi substream from client */
89static void bcd2000_midi_input_trigger(struct snd_rawmidi_substream *substream,
90 int up)
91{
92 struct bcd2000 *bcd2k = substream->rmidi->private_data;
93 bcd2k->midi_receive_substream = up ? substream : NULL;
94}
95
96static void bcd2000_midi_handle_input(struct bcd2000 *bcd2k,
97 const unsigned char *buf, unsigned int buf_len)
98{
99 unsigned int payload_length, tocopy;
100 struct snd_rawmidi_substream *midi_receive_substream;
101
6aa7de05 102 midi_receive_substream = READ_ONCE(bcd2k->midi_receive_substream);
b47a2229
MK
103 if (!midi_receive_substream)
104 return;
105
106 bcd2000_dump_buffer(PREFIX "received from device: ", buf, buf_len);
107
108 if (buf_len < 2)
109 return;
110
111 payload_length = buf[0];
112
113 /* ignore packets without payload */
114 if (payload_length == 0)
115 return;
116
117 tocopy = min(payload_length, buf_len-1);
118
119 bcd2000_dump_buffer(PREFIX "sending to userspace: ",
120 &buf[1], tocopy);
121
122 snd_rawmidi_receive(midi_receive_substream,
123 &buf[1], tocopy);
124}
125
126static void bcd2000_midi_send(struct bcd2000 *bcd2k)
127{
128 int len, ret;
129 struct snd_rawmidi_substream *midi_out_substream;
130
131 BUILD_BUG_ON(sizeof(device_cmd_prefix) >= BUFSIZE);
132
6aa7de05 133 midi_out_substream = READ_ONCE(bcd2k->midi_out_substream);
b47a2229
MK
134 if (!midi_out_substream)
135 return;
136
137 /* copy command prefix bytes */
138 memcpy(bcd2k->midi_out_buf, device_cmd_prefix,
139 sizeof(device_cmd_prefix));
140
141 /*
142 * get MIDI packet and leave space for command prefix
143 * and payload length
144 */
145 len = snd_rawmidi_transmit(midi_out_substream,
146 bcd2k->midi_out_buf + 3, BUFSIZE - 3);
147
148 if (len < 0)
149 dev_err(&bcd2k->dev->dev, "%s: snd_rawmidi_transmit error %d\n",
150 __func__, len);
151
152 if (len <= 0)
153 return;
154
155 /* set payload length */
156 bcd2k->midi_out_buf[2] = len;
157 bcd2k->midi_out_urb->transfer_buffer_length = BUFSIZE;
158
159 bcd2000_dump_buffer(PREFIX "sending to device: ",
160 bcd2k->midi_out_buf, len+3);
161
162 /* send packet to the BCD2000 */
163 ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_ATOMIC);
164 if (ret < 0)
165 dev_err(&bcd2k->dev->dev, PREFIX
166 "%s (%p): usb_submit_urb() failed, ret=%d, len=%d\n",
167 __func__, midi_out_substream, ret, len);
168 else
169 bcd2k->midi_out_active = 1;
170}
171
172static int bcd2000_midi_output_open(struct snd_rawmidi_substream *substream)
173{
174 return 0;
175}
176
177static int bcd2000_midi_output_close(struct snd_rawmidi_substream *substream)
178{
179 struct bcd2000 *bcd2k = substream->rmidi->private_data;
180
181 if (bcd2k->midi_out_active) {
182 usb_kill_urb(bcd2k->midi_out_urb);
183 bcd2k->midi_out_active = 0;
184 }
185
186 return 0;
187}
188
189/* (de)register midi substream from client */
190static void bcd2000_midi_output_trigger(struct snd_rawmidi_substream *substream,
191 int up)
192{
193 struct bcd2000 *bcd2k = substream->rmidi->private_data;
194
195 if (up) {
196 bcd2k->midi_out_substream = substream;
197 /* check if there is data userspace wants to send */
198 if (!bcd2k->midi_out_active)
199 bcd2000_midi_send(bcd2k);
200 } else {
201 bcd2k->midi_out_substream = NULL;
202 }
203}
204
205static void bcd2000_output_complete(struct urb *urb)
206{
207 struct bcd2000 *bcd2k = urb->context;
208
209 bcd2k->midi_out_active = 0;
210
211 if (urb->status)
212 dev_warn(&urb->dev->dev,
213 PREFIX "output urb->status: %d\n", urb->status);
214
215 if (urb->status == -ESHUTDOWN)
216 return;
217
218 /* check if there is more data userspace wants to send */
219 bcd2000_midi_send(bcd2k);
220}
221
222static void bcd2000_input_complete(struct urb *urb)
223{
224 int ret;
225 struct bcd2000 *bcd2k = urb->context;
226
227 if (urb->status)
228 dev_warn(&urb->dev->dev,
229 PREFIX "input urb->status: %i\n", urb->status);
230
231 if (!bcd2k || urb->status == -ESHUTDOWN)
232 return;
233
234 if (urb->actual_length > 0)
235 bcd2000_midi_handle_input(bcd2k, urb->transfer_buffer,
236 urb->actual_length);
237
238 /* return URB to device */
239 ret = usb_submit_urb(bcd2k->midi_in_urb, GFP_ATOMIC);
240 if (ret < 0)
241 dev_err(&bcd2k->dev->dev, PREFIX
242 "%s: usb_submit_urb() failed, ret=%d\n",
243 __func__, ret);
244}
245
f43e5407 246static const struct snd_rawmidi_ops bcd2000_midi_output = {
b47a2229
MK
247 .open = bcd2000_midi_output_open,
248 .close = bcd2000_midi_output_close,
249 .trigger = bcd2000_midi_output_trigger,
250};
251
f43e5407 252static const struct snd_rawmidi_ops bcd2000_midi_input = {
b47a2229
MK
253 .open = bcd2000_midi_input_open,
254 .close = bcd2000_midi_input_close,
255 .trigger = bcd2000_midi_input_trigger,
256};
257
258static void bcd2000_init_device(struct bcd2000 *bcd2k)
259{
260 int ret;
261
262 init_usb_anchor(&bcd2k->anchor);
263 usb_anchor_urb(bcd2k->midi_out_urb, &bcd2k->anchor);
264 usb_anchor_urb(bcd2k->midi_in_urb, &bcd2k->anchor);
265
266 /* copy init sequence into buffer */
267 memcpy(bcd2k->midi_out_buf, bcd2000_init_sequence, 52);
268 bcd2k->midi_out_urb->transfer_buffer_length = 52;
269
270 /* submit sequence */
271 ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_KERNEL);
272 if (ret < 0)
273 dev_err(&bcd2k->dev->dev, PREFIX
274 "%s: usb_submit_urb() out failed, ret=%d: ",
275 __func__, ret);
276 else
277 bcd2k->midi_out_active = 1;
278
279 /* pass URB to device to enable button and controller events */
280 ret = usb_submit_urb(bcd2k->midi_in_urb, GFP_KERNEL);
281 if (ret < 0)
282 dev_err(&bcd2k->dev->dev, PREFIX
283 "%s: usb_submit_urb() in failed, ret=%d: ",
284 __func__, ret);
285
286 /* ensure initialization is finished */
287 usb_wait_anchor_empty_timeout(&bcd2k->anchor, 1000);
288}
289
290static int bcd2000_init_midi(struct bcd2000 *bcd2k)
291{
292 int ret;
293 struct snd_rawmidi *rmidi;
294
295 ret = snd_rawmidi_new(bcd2k->card, bcd2k->card->shortname, 0,
296 1, /* output */
297 1, /* input */
298 &rmidi);
299
300 if (ret < 0)
301 return ret;
302
75b1a8f9 303 strscpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name));
b47a2229
MK
304
305 rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
306 rmidi->private_data = bcd2k;
307
308 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
309 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
310 &bcd2000_midi_output);
311
312 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
313 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
314 &bcd2000_midi_input);
315
316 bcd2k->rmidi = rmidi;
317
318 bcd2k->midi_in_urb = usb_alloc_urb(0, GFP_KERNEL);
319 bcd2k->midi_out_urb = usb_alloc_urb(0, GFP_KERNEL);
320
321 if (!bcd2k->midi_in_urb || !bcd2k->midi_out_urb) {
322 dev_err(&bcd2k->dev->dev, PREFIX "usb_alloc_urb failed\n");
323 return -ENOMEM;
324 }
325
326 usb_fill_int_urb(bcd2k->midi_in_urb, bcd2k->dev,
327 usb_rcvintpipe(bcd2k->dev, 0x81),
328 bcd2k->midi_in_buf, BUFSIZE,
329 bcd2000_input_complete, bcd2k, 1);
330
331 usb_fill_int_urb(bcd2k->midi_out_urb, bcd2k->dev,
332 usb_sndintpipe(bcd2k->dev, 0x1),
333 bcd2k->midi_out_buf, BUFSIZE,
334 bcd2000_output_complete, bcd2k, 1);
335
6815a0b4
TI
336 /* sanity checks of EPs before actually submitting */
337 if (usb_urb_ep_type_check(bcd2k->midi_in_urb) ||
338 usb_urb_ep_type_check(bcd2k->midi_out_urb)) {
339 dev_err(&bcd2k->dev->dev, "invalid MIDI EP\n");
340 return -EINVAL;
341 }
342
b47a2229
MK
343 bcd2000_init_device(bcd2k);
344
345 return 0;
346}
347
348static void bcd2000_free_usb_related_resources(struct bcd2000 *bcd2k,
349 struct usb_interface *interface)
350{
ffb2759d
ZM
351 usb_kill_urb(bcd2k->midi_out_urb);
352 usb_kill_urb(bcd2k->midi_in_urb);
b47a2229
MK
353
354 usb_free_urb(bcd2k->midi_out_urb);
355 usb_free_urb(bcd2k->midi_in_urb);
356
357 if (bcd2k->intf) {
358 usb_set_intfdata(bcd2k->intf, NULL);
359 bcd2k->intf = NULL;
360 }
361}
362
363static int bcd2000_probe(struct usb_interface *interface,
364 const struct usb_device_id *usb_id)
365{
366 struct snd_card *card;
367 struct bcd2000 *bcd2k;
368 unsigned int card_index;
369 char usb_path[32];
370 int err;
371
372 mutex_lock(&devices_mutex);
373
374 for (card_index = 0; card_index < SNDRV_CARDS; ++card_index)
375 if (!test_bit(card_index, devices_used))
376 break;
377
378 if (card_index >= SNDRV_CARDS) {
379 mutex_unlock(&devices_mutex);
380 return -ENOENT;
381 }
382
383 err = snd_card_new(&interface->dev, index[card_index], id[card_index],
384 THIS_MODULE, sizeof(*bcd2k), &card);
385 if (err < 0) {
386 mutex_unlock(&devices_mutex);
387 return err;
388 }
389
390 bcd2k = card->private_data;
391 bcd2k->dev = interface_to_usbdev(interface);
392 bcd2k->card = card;
393 bcd2k->card_index = card_index;
394 bcd2k->intf = interface;
395
396 snd_card_set_dev(card, &interface->dev);
397
398 strncpy(card->driver, "snd-bcd2000", sizeof(card->driver));
399 strncpy(card->shortname, "BCD2000", sizeof(card->shortname));
400 usb_make_path(bcd2k->dev, usb_path, sizeof(usb_path));
401 snprintf(bcd2k->card->longname, sizeof(bcd2k->card->longname),
402 "Behringer BCD2000 at %s",
403 usb_path);
404
405 err = bcd2000_init_midi(bcd2k);
406 if (err < 0)
407 goto probe_error;
408
409 err = snd_card_register(card);
410 if (err < 0)
411 goto probe_error;
412
413 usb_set_intfdata(interface, bcd2k);
414 set_bit(card_index, devices_used);
415
416 mutex_unlock(&devices_mutex);
417 return 0;
418
419probe_error:
420 dev_info(&bcd2k->dev->dev, PREFIX "error during probing");
421 bcd2000_free_usb_related_resources(bcd2k, interface);
422 snd_card_free(card);
423 mutex_unlock(&devices_mutex);
424 return err;
425}
426
427static void bcd2000_disconnect(struct usb_interface *interface)
428{
429 struct bcd2000 *bcd2k = usb_get_intfdata(interface);
430
431 if (!bcd2k)
432 return;
433
434 mutex_lock(&devices_mutex);
435
436 /* make sure that userspace cannot create new requests */
437 snd_card_disconnect(bcd2k->card);
438
439 bcd2000_free_usb_related_resources(bcd2k, interface);
440
441 clear_bit(bcd2k->card_index, devices_used);
442
443 snd_card_free_when_closed(bcd2k->card);
444
445 mutex_unlock(&devices_mutex);
446}
447
448static struct usb_driver bcd2000_driver = {
449 .name = "snd-bcd2000",
450 .probe = bcd2000_probe,
451 .disconnect = bcd2000_disconnect,
452 .id_table = id_table,
453};
454
455module_usb_driver(bcd2000_driver);
456
457MODULE_DEVICE_TABLE(usb, id_table);
458MODULE_AUTHOR("Mario Kicherer, dev@kicherer.org");
459MODULE_DESCRIPTION("Behringer BCD2000 driver");
460MODULE_LICENSE("GPL");