aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/caiaq
diff options
context:
space:
mode:
authorWilliam Light <wrl@illest.net>2011-10-10 11:54:23 -0400
committerTakashi Iwai <tiwai@suse.de>2011-10-13 02:16:46 -0400
commite653510a27e63b41a5bae3c46eb093375e17ca2d (patch)
treef4fd7eed75963295c074ff08e517e90b19db5287 /sound/usb/caiaq
parent3d37fbe44112b06279efa04ad91a0e4b7a0c600c (diff)
ALSA: snd-usb-caiaq: Add support for Maschine
This adds partial support for the Maschine controller by Native Instruments. Supported now are the 1x1 MIDI interface and the 41 buttons, 11 endless rotary encoders, and 16 pressure-sensitive drum pads. Still to work on are the dimmable LEDs and the two monochrome screens. Signed-off-by: William Light <wrl@illest.net> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/caiaq')
-rw-r--r--sound/usb/caiaq/device.c8
-rw-r--r--sound/usb/caiaq/device.h1
-rw-r--r--sound/usb/caiaq/input.c151
3 files changed, 158 insertions, 2 deletions
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 45bc4a2dc6f..3eb605bd950 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -50,7 +50,8 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
50 "{Native Instruments, Session I/O}," 50 "{Native Instruments, Session I/O},"
51 "{Native Instruments, GuitarRig mobile}" 51 "{Native Instruments, GuitarRig mobile}"
52 "{Native Instruments, Traktor Kontrol X1}" 52 "{Native Instruments, Traktor Kontrol X1}"
53 "{Native Instruments, Traktor Kontrol S4}"); 53 "{Native Instruments, Traktor Kontrol S4}"
54 "{Native Instruments, Maschine Controller}");
54 55
55static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ 56static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
56static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ 57static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
@@ -146,6 +147,11 @@ static struct usb_device_id snd_usb_id_table[] = {
146 .idVendor = USB_VID_NATIVEINSTRUMENTS, 147 .idVendor = USB_VID_NATIVEINSTRUMENTS,
147 .idProduct = USB_PID_TRAKTORAUDIO2 148 .idProduct = USB_PID_TRAKTORAUDIO2
148 }, 149 },
150 {
151 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
152 .idVendor = USB_VID_NATIVEINSTRUMENTS,
153 .idProduct = USB_PID_MASCHINECONTROLLER
154 },
149 { /* terminator */ } 155 { /* terminator */ }
150}; 156};
151 157
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index 3f9c6339ae9..562b0bff9c4 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -18,6 +18,7 @@
18#define USB_PID_TRAKTORKONTROLX1 0x2305 18#define USB_PID_TRAKTORKONTROLX1 0x2305
19#define USB_PID_TRAKTORKONTROLS4 0xbaff 19#define USB_PID_TRAKTORKONTROLS4 0xbaff
20#define USB_PID_TRAKTORAUDIO2 0x041d 20#define USB_PID_TRAKTORAUDIO2 0x041d
21#define USB_PID_MASCHINECONTROLLER 0x0808
21 22
22#define EP1_BUFSIZE 64 23#define EP1_BUFSIZE 64
23#define EP4_BUFSIZE 512 24#define EP4_BUFSIZE 512
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index 9efb92e4090..26a121b42c3 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -67,6 +67,61 @@ static unsigned short keycode_kore[] = {
67 KEY_BRL_DOT5 67 KEY_BRL_DOT5
68}; 68};
69 69
70#define MASCHINE_BUTTONS (42)
71#define MASCHINE_BUTTON(X) ((X) + BTN_MISC)
72#define MASCHINE_PADS (16)
73#define MASCHINE_PAD(X) ((X) + ABS_PRESSURE)
74
75static unsigned short keycode_maschine[] = {
76 MASCHINE_BUTTON(40), /* mute */
77 MASCHINE_BUTTON(39), /* solo */
78 MASCHINE_BUTTON(38), /* select */
79 MASCHINE_BUTTON(37), /* duplicate */
80 MASCHINE_BUTTON(36), /* navigate */
81 MASCHINE_BUTTON(35), /* pad mode */
82 MASCHINE_BUTTON(34), /* pattern */
83 MASCHINE_BUTTON(33), /* scene */
84 KEY_RESERVED, /* spacer */
85
86 MASCHINE_BUTTON(30), /* rec */
87 MASCHINE_BUTTON(31), /* erase */
88 MASCHINE_BUTTON(32), /* shift */
89 MASCHINE_BUTTON(28), /* grid */
90 MASCHINE_BUTTON(27), /* > */
91 MASCHINE_BUTTON(26), /* < */
92 MASCHINE_BUTTON(25), /* restart */
93
94 MASCHINE_BUTTON(21), /* E */
95 MASCHINE_BUTTON(22), /* F */
96 MASCHINE_BUTTON(23), /* G */
97 MASCHINE_BUTTON(24), /* H */
98 MASCHINE_BUTTON(20), /* D */
99 MASCHINE_BUTTON(19), /* C */
100 MASCHINE_BUTTON(18), /* B */
101 MASCHINE_BUTTON(17), /* A */
102
103 MASCHINE_BUTTON(0), /* control */
104 MASCHINE_BUTTON(2), /* browse */
105 MASCHINE_BUTTON(4), /* < */
106 MASCHINE_BUTTON(6), /* snap */
107 MASCHINE_BUTTON(7), /* autowrite */
108 MASCHINE_BUTTON(5), /* > */
109 MASCHINE_BUTTON(3), /* sampling */
110 MASCHINE_BUTTON(1), /* step */
111
112 MASCHINE_BUTTON(15), /* 8 softkeys */
113 MASCHINE_BUTTON(14),
114 MASCHINE_BUTTON(13),
115 MASCHINE_BUTTON(12),
116 MASCHINE_BUTTON(11),
117 MASCHINE_BUTTON(10),
118 MASCHINE_BUTTON(9),
119 MASCHINE_BUTTON(8),
120
121 MASCHINE_BUTTON(16), /* note repeat */
122 MASCHINE_BUTTON(29) /* play */
123};
124
70#define KONTROLX1_INPUTS (40) 125#define KONTROLX1_INPUTS (40)
71#define KONTROLS4_BUTTONS (12 * 8) 126#define KONTROLS4_BUTTONS (12 * 8)
72#define KONTROLS4_AXIS (46) 127#define KONTROLS4_AXIS (46)
@@ -218,6 +273,29 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
218 input_report_abs(input_dev, ABS_HAT3Y, i); 273 input_report_abs(input_dev, ABS_HAT3Y, i);
219 input_sync(input_dev); 274 input_sync(input_dev);
220 break; 275 break;
276
277 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
278 /* 4 under the left screen */
279 input_report_abs(input_dev, ABS_HAT0X, decode_erp(buf[21], buf[20]));
280 input_report_abs(input_dev, ABS_HAT0Y, decode_erp(buf[15], buf[14]));
281 input_report_abs(input_dev, ABS_HAT1X, decode_erp(buf[9], buf[8]));
282 input_report_abs(input_dev, ABS_HAT1Y, decode_erp(buf[3], buf[2]));
283
284 /* 4 under the right screen */
285 input_report_abs(input_dev, ABS_HAT2X, decode_erp(buf[19], buf[18]));
286 input_report_abs(input_dev, ABS_HAT2Y, decode_erp(buf[13], buf[12]));
287 input_report_abs(input_dev, ABS_HAT3X, decode_erp(buf[7], buf[6]));
288 input_report_abs(input_dev, ABS_HAT3Y, decode_erp(buf[1], buf[0]));
289
290 /* volume */
291 input_report_abs(input_dev, ABS_RX, decode_erp(buf[17], buf[16]));
292 /* tempo */
293 input_report_abs(input_dev, ABS_RY, decode_erp(buf[11], buf[10]));
294 /* swing */
295 input_report_abs(input_dev, ABS_RZ, decode_erp(buf[5], buf[4]));
296
297 input_sync(input_dev);
298 break;
221 } 299 }
222} 300}
223 301
@@ -400,6 +478,25 @@ static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
400 input_sync(dev->input_dev); 478 input_sync(dev->input_dev);
401} 479}
402 480
481#define MASCHINE_MSGBLOCK_SIZE 2
482
483static void snd_usb_caiaq_maschine_dispatch(struct snd_usb_caiaqdev *dev,
484 const unsigned char *buf,
485 unsigned int len)
486{
487 unsigned int i, pad_id;
488 uint16_t pressure;
489
490 for (i = 0; i < MASCHINE_PADS; i++) {
491 pressure = be16_to_cpu(buf[i * 2] << 8 | buf[(i * 2) + 1]);
492 pad_id = pressure >> 12;
493
494 input_report_abs(dev->input_dev, MASCHINE_PAD(pad_id), pressure & 0xfff);
495 }
496
497 input_sync(dev->input_dev);
498}
499
403static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb) 500static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
404{ 501{
405 struct snd_usb_caiaqdev *dev = urb->context; 502 struct snd_usb_caiaqdev *dev = urb->context;
@@ -425,6 +522,13 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
425 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): 522 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
426 snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length); 523 snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length);
427 break; 524 break;
525
526 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
527 if (urb->actual_length < (MASCHINE_PADS * MASCHINE_MSGBLOCK_SIZE))
528 goto requeue;
529
530 snd_usb_caiaq_maschine_dispatch(dev, buf, urb->actual_length);
531 break;
428 } 532 }
429 533
430requeue: 534requeue:
@@ -444,6 +548,7 @@ static int snd_usb_caiaq_input_open(struct input_dev *idev)
444 switch (dev->chip.usb_id) { 548 switch (dev->chip.usb_id) {
445 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): 549 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
446 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): 550 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
551 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
447 if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0) 552 if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
448 return -EIO; 553 return -EIO;
449 break; 554 break;
@@ -462,6 +567,7 @@ static void snd_usb_caiaq_input_close(struct input_dev *idev)
462 switch (dev->chip.usb_id) { 567 switch (dev->chip.usb_id) {
463 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): 568 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
464 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): 569 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
570 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
465 usb_kill_urb(dev->ep4_in_urb); 571 usb_kill_urb(dev->ep4_in_urb);
466 break; 572 break;
467 } 573 }
@@ -652,6 +758,50 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
652 758
653 break; 759 break;
654 760
761 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
762 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
763 input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
764 BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) |
765 BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) |
766 BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) |
767 BIT_MASK(ABS_RX) | BIT_MASK(ABS_RY) |
768 BIT_MASK(ABS_RZ);
769
770 BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_maschine));
771 memcpy(dev->keycode, keycode_maschine, sizeof(keycode_maschine));
772 input->keycodemax = ARRAY_SIZE(keycode_maschine);
773
774 for (i = 0; i < MASCHINE_PADS; i++) {
775 input->absbit[0] |= MASCHINE_PAD(i);
776 input_set_abs_params(input, MASCHINE_PAD(i), 0, 0xfff, 5, 10);
777 }
778
779 input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10);
780 input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10);
781 input_set_abs_params(input, ABS_HAT1X, 0, 999, 0, 10);
782 input_set_abs_params(input, ABS_HAT1Y, 0, 999, 0, 10);
783 input_set_abs_params(input, ABS_HAT2X, 0, 999, 0, 10);
784 input_set_abs_params(input, ABS_HAT2Y, 0, 999, 0, 10);
785 input_set_abs_params(input, ABS_HAT3X, 0, 999, 0, 10);
786 input_set_abs_params(input, ABS_HAT3Y, 0, 999, 0, 10);
787 input_set_abs_params(input, ABS_RX, 0, 999, 0, 10);
788 input_set_abs_params(input, ABS_RY, 0, 999, 0, 10);
789 input_set_abs_params(input, ABS_RZ, 0, 999, 0, 10);
790
791 dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
792 if (!dev->ep4_in_urb) {
793 ret = -ENOMEM;
794 goto exit_free_idev;
795 }
796
797 usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
798 usb_rcvbulkpipe(usb_dev, 0x4),
799 dev->ep4_in_buf, EP4_BUFSIZE,
800 snd_usb_caiaq_ep4_reply_dispatch, dev);
801
802 snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
803 break;
804
655 default: 805 default:
656 /* no input methods supported on this device */ 806 /* no input methods supported on this device */
657 goto exit_free_idev; 807 goto exit_free_idev;
@@ -690,4 +840,3 @@ void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
690 input_unregister_device(dev->input_dev); 840 input_unregister_device(dev->input_dev);
691 dev->input_dev = NULL; 841 dev->input_dev = NULL;
692} 842}
693