Skip to content

Commit

Permalink
[ALSA] usb-audio: fix parsing of SysEx messages from CME keyboards
Browse files Browse the repository at this point in the history
When CME keyboards send a SysEx message (e.g. master volume), the USB
packet uses a format different from the standard format.  Parsing this
packet according to the specification corrupts the SysEx message itself
and can cause the following MIDI messages to be misinterpreted, too.
This patch adds a workaround for this case.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
  • Loading branch information
Clemens Ladisch authored and Jaroslav Kysela committed Oct 16, 2007
1 parent 20a45e8 commit 61870ae
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions sound/usb/usbmidi.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,20 @@ static void snd_usbmidi_maudio_broken_running_status_input(
}
}

/*
* CME protocol: like the standard protocol, but SysEx commands are sent as a
* single USB packet preceded by a 0x0F byte.
*/
static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep,
uint8_t *buffer, int buffer_length)
{
if (buffer_length < 2 || (buffer[0] & 0x0f) != 0x0f)
snd_usbmidi_standard_input(ep, buffer, buffer_length);
else
snd_usbmidi_input_data(ep, buffer[0] >> 4,
&buffer[1], buffer_length - 1);
}

/*
* Adds one USB MIDI packet to the output buffer.
*/
Expand Down Expand Up @@ -572,6 +586,12 @@ static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
.output_packet = snd_usbmidi_output_standard_packet,
};

static struct usb_protocol_ops snd_usbmidi_cme_ops = {
.input = snd_usbmidi_cme_input,
.output = snd_usbmidi_standard_output,
.output_packet = snd_usbmidi_output_standard_packet,
};

/*
* Novation USB MIDI protocol: number of data bytes is in the first byte
* (when receiving) (+1!) or in the second byte (when sending); data begins
Expand Down Expand Up @@ -1690,6 +1710,7 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
break;
case QUIRK_MIDI_CME:
umidi->usb_protocol_ops = &snd_usbmidi_cme_ops;
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break;
default:
Expand Down

0 comments on commit 61870ae

Please sign in to comment.