MIDI driver for Behringer BCD2000 USB device
PATCH v6 1/1 MIDI driver for Behringer BCD2000 USB device
This patch adds initial support for the Behringer BCD2000 USB DJ controller. At the moment, only the MIDI part of the device is working, i.e. knobs, buttons and LEDs.
I also plan to add support for the audio part, but I assume that this will require more effort than the rather simple MIDI interface. Progress can be tracked at https://github.com/anyc/snd-usb-bcd2000.
Changes since v5:
- use kernel bitmap functions for devices_used
Changes since v4:
- devices_used as array to support arbitrary number of SNDRV_CARDS
- removed unused array "enable"
Changes since v3:
- applied style and snd_printk changes as suggested by Daniel Mack
Changes since v2:
- applied more changes from Daniel Mack and Clemens Ladisch
Changes since v1:
- fixed the various code style issues, thanks to Daniel Mack and checkpatch.pl.
--- sound/usb/Kconfig | 13 ++ sound/usb/Makefile | 2 +- sound/usb/bcd2000/Makefile | 3 + sound/usb/bcd2000/bcd2000.c | 488 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 505 insertions(+), 1 deletion(-) create mode 100644 sound/usb/bcd2000/Makefile create mode 100644 sound/usb/bcd2000/bcd2000.c
sound/usb/Kconfig +13 -0
@@ -146,5 +146,18 @@ config SND_USB_HIFACE To compile this driver as a module, choose M here: the module will be called snd-usb-hiface. +config SND_BCD2000 + tristate "Behringer BCD2000 MIDI driver" + select SND_RAWMIDI + help + Say Y here to include MIDI support for the Behringer BCD2000 DJ + controller. + + Audio support is still work-in-progress at + https://github.com/anyc/snd-usb-bcd2000 + + To compile this driver as a module, choose M here: the module + will be called snd-bcd2000. + endif # SND_USB
sound/usb/Makefile +1 -1
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o -obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ +obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/
sound/usb/bcd2000/Makefile new file +3 -0
@@ -0,0 +1,3 @@ +snd-bcd2000-y := bcd2000.o + +obj-$(CONFIG_SND_BCD2000) += snd-bcd2000.o
sound/usb/bcd2000/bcd2000.c new file +488 -0
488 lines not on this page · raw message
Signature · 1 line
1.8.3.2
sound/usb/bcd2000/bcd2000.c line 50
Quoted 9 lines · Mario Kicherer
sound/usb/bcd2000/bcd2000.c new file +9
-0+static unsigned char bcd2000_init_sequence[] = { +0x07 ,0x00 ,0x00 ,0x00 ,0x78 ,0x48 ,0x1c ,0x81 , +0xc4 ,0x00 ,0x00 ,0x00 ,0x5e ,0x53 ,0x4a ,0xf7 , +0x18 ,0xfa ,0x11 ,0xff ,0x6c ,0xf3 ,0x90 ,0xff , +0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x00 ,0x00 , +0x18 ,0xfa ,0x11 ,0xff ,0x14 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0xf2 ,0x34 ,0x4a ,0xf7 , +0x18 ,0xfa ,0x11 ,0xff +};
I wonder how much of this is the actual init sequence, and how much is random garbage. :-)
sound/usb/bcd2000/bcd2000.c line 128
Quoted 6 lines
sound/usb/bcd2000/bcd2000.c new file +6
-0+/* +* Packet structure: mm nn oo (pp) +* mm: payload length +* nn: MIDI command or note +* oo: note or velocity +* pp: velocity
The device often sends data as single-byte packets, so the structure actually is "length data...".
sound/usb/bcd2000/bcd2000.c line 155
Quoted 3 lines
sound/usb/bcd2000/bcd2000.c new file +3
-0+/* copy the "set LED" command bytes */ +memcpy (bcd2k->midi_out_buf, device_cmd_prefix, +sizeof (device_cmd_prefix));
This is also used for data request and input selection, so it's not "set LED" but just "MIDI output".
sound/usb/bcd2000/bcd2000.c line 249
Quoted 6 lines
sound/usb/bcd2000/bcd2000.c new file +6
-0+static void bcd2000_input_complete (struct urb *urb) +{ +if (urb->status) { +dev_warn (dev,PREFIX "input urb->status: %i\n" , urb->status); +return ; + }
This will stop the input even on transient errors.
sound/usb/bcd2000/bcd2000.c line 261
Quoted 4 lines
sound/usb/bcd2000/bcd2000.c new file +4
-0+/* acknowledge received packet */ + ret =usb_submit_urb (bcd2k->midi_in_urb,GFP_ATOMIC ); +if (ret <0 ) +dev_err (dev,"unable to submit urb. OOM!?\n" );
Don't guess, just show ret. :)
sound/usb/bcd2000/bcd2000.c line 413
Quoted 6 lines
sound/usb/bcd2000/bcd2000.c new file +6
-0+strcpy (card->driver,DEVICE_NAME ); +strcpy (card->shortname,DEVICE_SHORTNAME ); +usb_make_path (bcd2k->dev, usb_path,sizeof (usb_path)); +snprintf (bcd2k->card->longname,sizeof (bcd2k->card->longname), +DEVICE_NAME ", at %s" , + usb_path);
$ cat /proc/asound/cards
...
18 [bcd2000 ]: Behringer BCD200bcd2000 - bcd2000
Behringer BCD2000, at usb-0000:00:13.1-3The driver name just identifies the driver, it does not need the vendor name. (And it should not overflow its buffer.)
The short name is shown to the user in many places, so it should be properly capitalized.
The long name does not need the comma.
sound/usb/bcd2000/bcd2000.c line 415
Quoted 1 line
sound/usb/bcd2000/bcd2000.c new file +1
-0+dev_info (&bcd2k->dev->dev,PREFIX "%s" , bcd2k->card->longname);
What use does this message have in the log?
Regards,
Clemens
Quoted 2 lines · Clemens Ladisch
I wonder how much of this is the actual init sequence, and how much is random garbage. :-)
Me too, but I want to make sure the module works before I start experimenting and risk modifying/damaging my device. Some bytes in between stay the same, some seem to change randomly everytime I plug in
the device.
Quoted 2 lines
The device often sends data as single-byte packets, so the structure actually is "length data...".
Yeah, it's a bit misleading here. I'll change this part.
Quoted 8 lines
sound/usb/bcd2000/bcd2000.c line 249
Quoted 6 lines
sound/usb/bcd2000/bcd2000.c new file +6
-0+static void bcd2000_input_complete (struct urb *urb) +{ +if (urb->status) { +dev_warn (dev,PREFIX "input urb->status: %i\n" , urb->status); +return ; + }This will stop the input even on transient errors.
Hm, so, it is important to send the "acknowledge" urb afterwards nonetheless?
Quoted 5 lines
$ cat /proc/asound/cards
...
18 [bcd2000 ]: Behringer BCD200bcd2000 - bcd2000
Behringer BCD2000, at usb-0000:00:13.1-3Quoted 7 lines
The driver name just identifies the driver, it does not need the vendor name. (And it should not overflow its buffer.)
The short name is shown to the user in many places, so it should be properly capitalized.
The long name does not need the comma.
I removed the macros and just placed the names in there directly as that's the only place they're used anyway.
Do you actually own a BCD2000?
Quoted 3 lines
sound/usb/bcd2000/bcd2000.c line 415
Quoted 1 line
sound/usb/bcd2000/bcd2000.c new file +1
-0+dev_info (&bcd2k->dev->dev,PREFIX "%s" , bcd2k->card->longname);What use does this message have in the log?
I saw this in another driver and thought this is common practice. I'll remove it then.
Thank you for your comments!
Mario
Quoted 10 lines · Mario Kicherer
Quoted 8 lines · Clemens Ladisch
sound/usb/bcd2000/bcd2000.c line 249
Quoted 6 lines
sound/usb/bcd2000/bcd2000.c new file +6
-0+static void bcd2000_input_complete (struct urb *urb) +{ +if (urb->status) { +dev_warn (dev,PREFIX "input urb->status: %i\n" , urb->status); +return ; + }This will stop the input even on transient errors.
Quoted 2 lines
Hm, so, it is important to send the "acknowledge" urb afterwards nonetheless?
This has nothing to do with acknowledging. Once the completion callback was called, the URB is again owned by your driver, and nothing happens unless you submit it again.
The only reason not to re-submit the URB is a permanent error (i.e., if the device has been unplugged).
Quoted 1 line
Do you actually own a BCD2000?
Yes.
Regards,
Clemens