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