blob: 010976d9ceb25fbc5b09552783dbc0a3c0e00451 [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001// SPDX-License-Identifier: GPL-2.0-or-later
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/*
3 * Behringer BCD2000 driver
4 *
5 * Copyright (C) 2014 Mario Kicherer (dev@kicherer.org)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00006 */
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
23static const struct usb_device_id id_table[] = {
24 { USB_DEVICE(0x1397, 0x00bd) },
25 { },
26};
27
Olivier Deprez157378f2022-04-04 15:47:50 +020028static const unsigned char device_cmd_prefix[] = {0x03, 0x00};
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000029
Olivier Deprez157378f2022-04-04 15:47:50 +020030static const unsigned char bcd2000_init_sequence[] = {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000031 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);
64static DECLARE_BITMAP(devices_used, SNDRV_CARDS);
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
102 midi_receive_substream = READ_ONCE(bcd2k->midi_receive_substream);
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
133 midi_out_substream = READ_ONCE(bcd2k->midi_out_substream);
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
246static const struct snd_rawmidi_ops bcd2000_midi_output = {
247 .open = bcd2000_midi_output_open,
248 .close = bcd2000_midi_output_close,
249 .trigger = bcd2000_midi_output_trigger,
250};
251
252static const struct snd_rawmidi_ops bcd2000_midi_input = {
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
303 strlcpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name));
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
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
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{
351 /* usb_kill_urb not necessary, urb is aborted automatically */
352
353 usb_free_urb(bcd2k->midi_out_urb);
354 usb_free_urb(bcd2k->midi_in_urb);
355
356 if (bcd2k->intf) {
357 usb_set_intfdata(bcd2k->intf, NULL);
358 bcd2k->intf = NULL;
359 }
360}
361
362static int bcd2000_probe(struct usb_interface *interface,
363 const struct usb_device_id *usb_id)
364{
365 struct snd_card *card;
366 struct bcd2000 *bcd2k;
367 unsigned int card_index;
368 char usb_path[32];
369 int err;
370
371 mutex_lock(&devices_mutex);
372
373 for (card_index = 0; card_index < SNDRV_CARDS; ++card_index)
374 if (!test_bit(card_index, devices_used))
375 break;
376
377 if (card_index >= SNDRV_CARDS) {
378 mutex_unlock(&devices_mutex);
379 return -ENOENT;
380 }
381
382 err = snd_card_new(&interface->dev, index[card_index], id[card_index],
383 THIS_MODULE, sizeof(*bcd2k), &card);
384 if (err < 0) {
385 mutex_unlock(&devices_mutex);
386 return err;
387 }
388
389 bcd2k = card->private_data;
390 bcd2k->dev = interface_to_usbdev(interface);
391 bcd2k->card = card;
392 bcd2k->card_index = card_index;
393 bcd2k->intf = interface;
394
395 snd_card_set_dev(card, &interface->dev);
396
397 strncpy(card->driver, "snd-bcd2000", sizeof(card->driver));
398 strncpy(card->shortname, "BCD2000", sizeof(card->shortname));
399 usb_make_path(bcd2k->dev, usb_path, sizeof(usb_path));
400 snprintf(bcd2k->card->longname, sizeof(bcd2k->card->longname),
401 "Behringer BCD2000 at %s",
402 usb_path);
403
404 err = bcd2000_init_midi(bcd2k);
405 if (err < 0)
406 goto probe_error;
407
408 err = snd_card_register(card);
409 if (err < 0)
410 goto probe_error;
411
412 usb_set_intfdata(interface, bcd2k);
413 set_bit(card_index, devices_used);
414
415 mutex_unlock(&devices_mutex);
416 return 0;
417
418probe_error:
419 dev_info(&bcd2k->dev->dev, PREFIX "error during probing");
420 bcd2000_free_usb_related_resources(bcd2k, interface);
421 snd_card_free(card);
422 mutex_unlock(&devices_mutex);
423 return err;
424}
425
426static void bcd2000_disconnect(struct usb_interface *interface)
427{
428 struct bcd2000 *bcd2k = usb_get_intfdata(interface);
429
430 if (!bcd2k)
431 return;
432
433 mutex_lock(&devices_mutex);
434
435 /* make sure that userspace cannot create new requests */
436 snd_card_disconnect(bcd2k->card);
437
438 bcd2000_free_usb_related_resources(bcd2k, interface);
439
440 clear_bit(bcd2k->card_index, devices_used);
441
442 snd_card_free_when_closed(bcd2k->card);
443
444 mutex_unlock(&devices_mutex);
445}
446
447static struct usb_driver bcd2000_driver = {
448 .name = "snd-bcd2000",
449 .probe = bcd2000_probe,
450 .disconnect = bcd2000_disconnect,
451 .id_table = id_table,
452};
453
454module_usb_driver(bcd2000_driver);
455
456MODULE_DEVICE_TABLE(usb, id_table);
457MODULE_AUTHOR("Mario Kicherer, dev@kicherer.org");
458MODULE_DESCRIPTION("Behringer BCD2000 driver");
459MODULE_LICENSE("GPL");