ALSA: line6: correct midi status byte when receiving data from podxt
authorArtem Egorkine <arteme@gmail.com>
Sun, 25 Dec 2022 10:57:27 +0000 (12:57 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 7 Jan 2023 11:07:35 +0000 (12:07 +0100)
commit 8508fa2e7472f673edbeedf1b1d2b7a6bb898ecc upstream.

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.

[ tiwai: fixed white spaces ]

Signed-off-by: Artem Egorkine <arteme@gmail.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20221225105728.1153989-1-arteme@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
sound/usb/line6/driver.c
sound/usb/line6/midi.c
sound/usb/line6/midibuf.c
sound/usb/line6/midibuf.h
sound/usb/line6/pod.c

index 8cca0befcf013f3d61e80f422cf6270364dc603e..de8bb9c914747d536119e81fba85e82cf6fff4f7 100644 (file)
@@ -304,7 +304,8 @@ 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,
+                                                  LINE6_MIDIBUF_READ_RX);
 
                        if (done <= 0)
                                break;
index 4f4ebe90f1a8e232d0352ab9b73f04af3981841b..10cc3208d0698a54c40ad47600f1ca8499f2716a 100644 (file)
@@ -60,7 +60,8 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
 
        for (;;) {
                done = line6_midibuf_read(mb, chunk,
-                                         LINE6_FALLBACK_MAXPACKETSIZE);
+                                         LINE6_FALLBACK_MAXPACKETSIZE,
+                                         LINE6_MIDIBUF_READ_TX);
 
                if (done == 0)
                        break;
index c931d48801ebed6626fdbfd0491d672d29c917b3..4622234723a6eadf0c411c8b911665cc088f5890 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "midibuf.h"
 
+
 static int midibuf_message_length(unsigned char code)
 {
        int message_length;
@@ -24,12 +25,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];
@@ -129,7 +125,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, int read_type)
 {
        int bytes_used;
        int length1, length2;
@@ -152,9 +148,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 (read_type == LINE6_MIDIBUF_READ_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;
index 6ea21ffb662715a54dc5aa39bba78ff3196c671b..187f49c975c280cd7506ad8de5d3166def33a746 100644 (file)
@@ -12,6 +12,9 @@
 #ifndef MIDIBUF_H
 #define MIDIBUF_H
 
+#define LINE6_MIDIBUF_READ_TX 0
+#define LINE6_MIDIBUF_READ_RX 1
+
 struct midi_buffer {
        unsigned char *buf;
        int size;
@@ -27,7 +30,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, int read_type);
 extern void line6_midibuf_reset(struct midi_buffer *mb);
 extern int line6_midibuf_write(struct midi_buffer *mb, unsigned char *data,
                               int length);
index aaa192aee883e2750467f7d3124cbb037afc7521..81c2abacc612f50f0ce60ddc8612fa3437defbe5 100644 (file)
@@ -169,8 +169,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
 };
 
 /* forward declarations: */