aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/midi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-26 11:41:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-26 11:41:25 -0400
commit2214482cb00e6da1397c2ecde5b392490eb9637f (patch)
tree7375817fa8b76741a0e362716b59860255e526ba /sound/usb/midi.c
parent13da9e200fe4740b02cd51e07ab454627e228920 (diff)
parentd21921215af2fe33190a3b5b166b145e607e537d (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: ALSA: emu10k1: allow high-resolution mixer controls ALSA: pcm: fix delta calculation at boundary wraparound ALSA: hda_intel: fix handling of non-completion stream interrupts ALSA: usb/caiaq: fix Traktor Kontrol X1 ABS_HAT2X axis ALSA: hda: Fix model quirk for Dell M1730 ALSA: hda - iMac9,1 sound fixes ALSA: hda: Use LPIB for Toshiba A100-259 ALSA: hda: Use LPIB for Acer Aspire 5110 ALSA: aw2-alsa.c: use pci_ids.h defines and fix checkpatch.pl noise ALSA: usb-audio: add support for Akai MPD16 ALSA: pcm: fix the fix of the runtime->boundary calculation
Diffstat (limited to 'sound/usb/midi.c')
-rw-r--r--sound/usb/midi.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 8b1e4b124a9f..46785643c66d 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -645,6 +645,105 @@ static struct usb_protocol_ops snd_usbmidi_cme_ops = {
645}; 645};
646 646
647/* 647/*
648 * AKAI MPD16 protocol:
649 *
650 * For control port (endpoint 1):
651 * ==============================
652 * One or more chunks consisting of first byte of (0x10 | msg_len) and then a
653 * SysEx message (msg_len=9 bytes long).
654 *
655 * For data port (endpoint 2):
656 * ===========================
657 * One or more chunks consisting of first byte of (0x20 | msg_len) and then a
658 * MIDI message (msg_len bytes long)
659 *
660 * Messages sent: Active Sense, Note On, Poly Pressure, Control Change.
661 */
662static void snd_usbmidi_akai_input(struct snd_usb_midi_in_endpoint *ep,
663 uint8_t *buffer, int buffer_length)
664{
665 unsigned int pos = 0;
666 unsigned int len = (unsigned int)buffer_length;
667 while (pos < len) {
668 unsigned int port = (buffer[pos] >> 4) - 1;
669 unsigned int msg_len = buffer[pos] & 0x0f;
670 pos++;
671 if (pos + msg_len <= len && port < 2)
672 snd_usbmidi_input_data(ep, 0, &buffer[pos], msg_len);
673 pos += msg_len;
674 }
675}
676
677#define MAX_AKAI_SYSEX_LEN 9
678
679static void snd_usbmidi_akai_output(struct snd_usb_midi_out_endpoint *ep,
680 struct urb *urb)
681{
682 uint8_t *msg;
683 int pos, end, count, buf_end;
684 uint8_t tmp[MAX_AKAI_SYSEX_LEN];
685 struct snd_rawmidi_substream *substream = ep->ports[0].substream;
686
687 if (!ep->ports[0].active)
688 return;
689
690 msg = urb->transfer_buffer + urb->transfer_buffer_length;
691 buf_end = ep->max_transfer - MAX_AKAI_SYSEX_LEN - 1;
692
693 /* only try adding more data when there's space for at least 1 SysEx */
694 while (urb->transfer_buffer_length < buf_end) {
695 count = snd_rawmidi_transmit_peek(substream,
696 tmp, MAX_AKAI_SYSEX_LEN);
697 if (!count) {
698 ep->ports[0].active = 0;
699 return;
700 }
701 /* try to skip non-SysEx data */
702 for (pos = 0; pos < count && tmp[pos] != 0xF0; pos++)
703 ;
704
705 if (pos > 0) {
706 snd_rawmidi_transmit_ack(substream, pos);
707 continue;
708 }
709
710 /* look for the start or end marker */
711 for (end = 1; end < count && tmp[end] < 0xF0; end++)
712 ;
713
714 /* next SysEx started before the end of current one */
715 if (end < count && tmp[end] == 0xF0) {
716 /* it's incomplete - drop it */
717 snd_rawmidi_transmit_ack(substream, end);
718 continue;
719 }
720 /* SysEx complete */
721 if (end < count && tmp[end] == 0xF7) {
722 /* queue it, ack it, and get the next one */
723 count = end + 1;
724 msg[0] = 0x10 | count;
725 memcpy(&msg[1], tmp, count);
726 snd_rawmidi_transmit_ack(substream, count);
727 urb->transfer_buffer_length += count + 1;
728 msg += count + 1;
729 continue;
730 }
731 /* less than 9 bytes and no end byte - wait for more */
732 if (count < MAX_AKAI_SYSEX_LEN) {
733 ep->ports[0].active = 0;
734 return;
735 }
736 /* 9 bytes and no end marker in sight - malformed, skip it */
737 snd_rawmidi_transmit_ack(substream, count);
738 }
739}
740
741static struct usb_protocol_ops snd_usbmidi_akai_ops = {
742 .input = snd_usbmidi_akai_input,
743 .output = snd_usbmidi_akai_output,
744};
745
746/*
648 * Novation USB MIDI protocol: number of data bytes is in the first byte 747 * Novation USB MIDI protocol: number of data bytes is in the first byte
649 * (when receiving) (+1!) or in the second byte (when sending); data begins 748 * (when receiving) (+1!) or in the second byte (when sending); data begins
650 * at the third byte. 749 * at the third byte.
@@ -1434,6 +1533,11 @@ static struct port_info {
1434 EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"), 1533 EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"),
1435 EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"), 1534 EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"),
1436 EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"), 1535 EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"),
1536 /* Akai MPD16 */
1537 CONTROL_PORT(0x09e8, 0x0062, 0, "%s Control"),
1538 PORT_INFO(0x09e8, 0x0062, 1, "%s MIDI", 0,
1539 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
1540 SNDRV_SEQ_PORT_TYPE_HARDWARE),
1437 /* Access Music Virus TI */ 1541 /* Access Music Virus TI */
1438 EXTERNAL_PORT(0x133e, 0x0815, 0, "%s MIDI"), 1542 EXTERNAL_PORT(0x133e, 0x0815, 0, "%s MIDI"),
1439 PORT_INFO(0x133e, 0x0815, 1, "%s Synth", 0, 1543 PORT_INFO(0x133e, 0x0815, 1, "%s Synth", 0,
@@ -2035,6 +2139,12 @@ int snd_usbmidi_create(struct snd_card *card,
2035 umidi->usb_protocol_ops = &snd_usbmidi_cme_ops; 2139 umidi->usb_protocol_ops = &snd_usbmidi_cme_ops;
2036 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); 2140 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
2037 break; 2141 break;
2142 case QUIRK_MIDI_AKAI:
2143 umidi->usb_protocol_ops = &snd_usbmidi_akai_ops;
2144 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
2145 /* endpoint 1 is input-only */
2146 endpoints[1].out_cables = 0;
2147 break;
2038 default: 2148 default:
2039 snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); 2149 snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
2040 err = -ENXIO; 2150 err = -ENXIO;