@@ -304,7 +304,7 @@ static void line6_data_received(struct urb *urb)
for (;;) {
done =
line6_midibuf_read(mb, line6->buffer_message,
- LINE6_MIDI_MESSAGE_MAXLEN);
+ LINE6_MIDI_MESSAGE_MAXLEN, 1);
if (done <= 0)
break;
@@ -56,7 +56,7 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
for (;;) {
done = line6_midibuf_read(mb, chunk,
- LINE6_FALLBACK_MAXPACKETSIZE);
+ LINE6_FALLBACK_MAXPACKETSIZE, 0);
if (done == 0)
break;
@@ -9,6 +9,22 @@
#include "midibuf.h"
+/* #define DUMP_BUFFERS */
+
+#ifdef DUMP_BUFFERS
+static void dump_buffer(char rx, const u8 *data, int length)
+{
+ const char* type = rx ? "rx" : "tx";
+ printk(KERN_DEBUG "%s packet: [", type);
+ for (; length > 0; ++data, --length)
+ printk(KERN_CONT " %02x", *data);
+ printk(KERN_CONT " ]\n");
+}
+#else
+#define dump_buffer(rx, data, length) /* nothing */
+#endif
+
+
static int midibuf_message_length(unsigned char code)
{
int message_length;
@@ -20,12 +36,7 @@ static int midibuf_message_length(unsigned char code)
message_length = length[(code >> 4) - 8];
} else {
- /*
- Note that according to the MIDI specification 0xf2 is
- the "Song Position Pointer", but this is used by Line 6
- to send sysex messages to the host.
- */
- static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1,
+ static const int length[] = { -1, 2, 2, 2, -1, -1, 1, 1, 1, -1,
1, 1, 1, -1, 1, 1
};
message_length = length[code & 0x0f];
@@ -125,7 +136,7 @@ int line6_midibuf_write(struct midi_buffer *this, unsigned char *data,
}
int line6_midibuf_read(struct midi_buffer *this, unsigned char *data,
- int length)
+ int length, char rx)
{
int bytes_used;
int length1, length2;
@@ -148,9 +159,22 @@ int line6_midibuf_read(struct midi_buffer *this, unsigned char *data,
length1 = this->size - this->pos_read;
- /* check MIDI command length */
command = this->buf[this->pos_read];
+ /*
+ PODxt always has status byte lower nibble set to 0010,
+ when it means to send 0000, so we correct if here so
+ that control/program changes come on channel 1 and
+ sysex message status byte is correct
+ */
+ if (rx) {
+ if (command == 0xb2 || command == 0xc2 || command == 0xf2) {
+ unsigned char fixed = command & 0xf0;
+ this->buf[this->pos_read] = fixed;
+ command = fixed;
+ }
+ }
+ /* check MIDI command length */
if (command & 0x80) {
midi_length = midibuf_message_length(command);
this->command_prev = command;
@@ -222,6 +246,8 @@ int line6_midibuf_read(struct midi_buffer *this, unsigned char *data,
this->pos_read = length2;
}
+ dump_buffer(rx, data, length + repeat);
+
if (repeat)
data[0] = this->command_prev;
@@ -23,7 +23,7 @@ extern void line6_midibuf_destroy(struct midi_buffer *mb);
extern int line6_midibuf_ignore(struct midi_buffer *mb, int length);
extern int line6_midibuf_init(struct midi_buffer *mb, int size, int split);
extern int line6_midibuf_read(struct midi_buffer *mb, unsigned char *data,
- int length);
+ int length, char rx);
extern void line6_midibuf_reset(struct midi_buffer *mb);
extern int line6_midibuf_write(struct midi_buffer *mb, unsigned char *data,
int length);
@@ -159,8 +159,9 @@ static struct line6_pcm_properties pod_pcm_properties = {
.bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
};
+
static const char pod_version_header[] = {
- 0xf2, 0x7e, 0x7f, 0x06, 0x02
+ 0xf0, 0x7e, 0x7f, 0x06, 0x02
};
static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
A PODxt device sends 0xb2, 0xc2 or 0xf2 as a status byte for MIDI messages over USB that should otherwise have a 0xb0, 0xc0 or 0xf0 status byte. This is usually corrected by the driver on other OSes. This fixes MIDI sysex messages sent by PODxt. Signed-off-by: Artem Egorkine <arteme@gmail.com> --- sound/usb/line6/driver.c | 2 +- sound/usb/line6/midi.c | 2 +- sound/usb/line6/midibuf.c | 42 +++++++++++++++++++++++++++++++-------- sound/usb/line6/midibuf.h | 2 +- sound/usb/line6/pod.c | 3 ++- 5 files changed, 39 insertions(+), 12 deletions(-)