aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/caiaq
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-03-22 08:13:37 -0400
committerTakashi Iwai <tiwai@suse.de>2010-03-22 11:10:41 -0400
commit6da7a2aa899f75116e1a62cef78c358ada9878b7 (patch)
tree64099b4ea88f717623ec720293727e5048a9bd37 /sound/usb/caiaq
parentfc8aa7b16a5fcfe9c6d0be9bb587f1fcedd9145f (diff)
ALSA: usb/caiaq: Add support for Traktor Kontrol X1
This device does not have audio controllers and backlit buttons only. Input data is handled over a dedicated USB endpoint. All functions are supported by the driver now. Signed-off-by: Daniel Mack <daniel@caiaq.de> Cc: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/caiaq')
-rw-r--r--sound/usb/caiaq/control.c99
-rw-r--r--sound/usb/caiaq/device.c8
-rw-r--r--sound/usb/caiaq/device.h24
-rw-r--r--sound/usb/caiaq/input.c162
4 files changed, 248 insertions, 45 deletions
diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c
index 537102ba6b9d..36ed703a7416 100644
--- a/sound/usb/caiaq/control.c
+++ b/sound/usb/caiaq/control.c
@@ -35,33 +35,41 @@ static int control_info(struct snd_kcontrol *kcontrol,
35 struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); 35 struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
36 int pos = kcontrol->private_value; 36 int pos = kcontrol->private_value;
37 int is_intval = pos & CNT_INTVAL; 37 int is_intval = pos & CNT_INTVAL;
38 unsigned int id = dev->chip.usb_id; 38 int maxval = 63;
39 39
40 uinfo->count = 1; 40 uinfo->count = 1;
41 pos &= ~CNT_INTVAL; 41 pos &= ~CNT_INTVAL;
42 42
43 if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ) 43 switch (dev->chip.usb_id) {
44 && (pos == 0)) { 44 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
45 /* current input mode of A8DJ */ 45 if (pos == 0) {
46 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 46 /* current input mode of A8DJ */
47 uinfo->value.integer.min = 0; 47 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
48 uinfo->value.integer.max = 2; 48 uinfo->value.integer.min = 0;
49 return 0; 49 uinfo->value.integer.max = 2;
50 } 50 return 0;
51 }
52 break;
51 53
52 if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ) 54 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
53 && (pos == 0)) { 55 if (pos == 0) {
54 /* current input mode of A4DJ */ 56 /* current input mode of A4DJ */
55 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 57 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
56 uinfo->value.integer.min = 0; 58 uinfo->value.integer.min = 0;
57 uinfo->value.integer.max = 1; 59 uinfo->value.integer.max = 1;
58 return 0; 60 return 0;
61 }
62 break;
63
64 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
65 maxval = 127;
66 break;
59 } 67 }
60 68
61 if (is_intval) { 69 if (is_intval) {
62 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 70 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
63 uinfo->value.integer.min = 0; 71 uinfo->value.integer.min = 0;
64 uinfo->value.integer.max = 64; 72 uinfo->value.integer.max = maxval;
65 } else { 73 } else {
66 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 74 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
67 uinfo->value.integer.min = 0; 75 uinfo->value.integer.min = 0;
@@ -102,9 +110,10 @@ static int control_put(struct snd_kcontrol *kcontrol,
102 struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); 110 struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
103 struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); 111 struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
104 int pos = kcontrol->private_value; 112 int pos = kcontrol->private_value;
113 unsigned char cmd = EP1_CMD_WRITE_IO;
105 114
106 if (dev->chip.usb_id == 115 switch (dev->chip.usb_id) {
107 USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { 116 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): {
108 /* A4DJ has only one control */ 117 /* A4DJ has only one control */
109 /* do not expose hardware input mode 0 */ 118 /* do not expose hardware input mode 0 */
110 dev->control_state[0] = ucontrol->value.integer.value[0] + 1; 119 dev->control_state[0] = ucontrol->value.integer.value[0] + 1;
@@ -113,10 +122,15 @@ static int control_put(struct snd_kcontrol *kcontrol,
113 return 1; 122 return 1;
114 } 123 }
115 124
125 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
126 cmd = EP1_CMD_DIMM_LEDS;
127 break;
128 }
129
116 if (pos & CNT_INTVAL) { 130 if (pos & CNT_INTVAL) {
117 dev->control_state[pos & ~CNT_INTVAL] 131 dev->control_state[pos & ~CNT_INTVAL]
118 = ucontrol->value.integer.value[0]; 132 = ucontrol->value.integer.value[0];
119 snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, 133 snd_usb_caiaq_send_command(dev, cmd,
120 dev->control_state, sizeof(dev->control_state)); 134 dev->control_state, sizeof(dev->control_state));
121 } else { 135 } else {
122 if (ucontrol->value.integer.value[0]) 136 if (ucontrol->value.integer.value[0])
@@ -124,7 +138,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
124 else 138 else
125 dev->control_state[pos / 8] &= ~(1 << (pos % 8)); 139 dev->control_state[pos / 8] &= ~(1 << (pos % 8));
126 140
127 snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, 141 snd_usb_caiaq_send_command(dev, cmd,
128 dev->control_state, sizeof(dev->control_state)); 142 dev->control_state, sizeof(dev->control_state));
129 } 143 }
130 144
@@ -273,6 +287,43 @@ static struct caiaq_controller a4dj_controller[] = {
273 { "Current input mode", 0 | CNT_INTVAL } 287 { "Current input mode", 0 | CNT_INTVAL }
274}; 288};
275 289
290static struct caiaq_controller kontrolx1_controller[] = {
291 { "LED FX A: ON", 7 | CNT_INTVAL },
292 { "LED FX A: 1", 6 | CNT_INTVAL },
293 { "LED FX A: 2", 5 | CNT_INTVAL },
294 { "LED FX A: 3", 4 | CNT_INTVAL },
295 { "LED FX B: ON", 3 | CNT_INTVAL },
296 { "LED FX B: 1", 2 | CNT_INTVAL },
297 { "LED FX B: 2", 1 | CNT_INTVAL },
298 { "LED FX B: 3", 0 | CNT_INTVAL },
299
300 { "LED Hotcue", 28 | CNT_INTVAL },
301 { "LED Shift (white)", 29 | CNT_INTVAL },
302 { "LED Shift (green)", 30 | CNT_INTVAL },
303
304 { "LED Deck A: FX1", 24 | CNT_INTVAL },
305 { "LED Deck A: FX2", 25 | CNT_INTVAL },
306 { "LED Deck A: IN", 17 | CNT_INTVAL },
307 { "LED Deck A: OUT", 16 | CNT_INTVAL },
308 { "LED Deck A: < BEAT", 19 | CNT_INTVAL },
309 { "LED Deck A: BEAT >", 18 | CNT_INTVAL },
310 { "LED Deck A: CUE/ABS", 21 | CNT_INTVAL },
311 { "LED Deck A: CUP/REL", 20 | CNT_INTVAL },
312 { "LED Deck A: PLAY", 23 | CNT_INTVAL },
313 { "LED Deck A: SYNC", 22 | CNT_INTVAL },
314
315 { "LED Deck B: FX1", 26 | CNT_INTVAL },
316 { "LED Deck B: FX2", 27 | CNT_INTVAL },
317 { "LED Deck B: IN", 15 | CNT_INTVAL },
318 { "LED Deck B: OUT", 14 | CNT_INTVAL },
319 { "LED Deck B: < BEAT", 13 | CNT_INTVAL },
320 { "LED Deck B: BEAT >", 12 | CNT_INTVAL },
321 { "LED Deck B: CUE/ABS", 11 | CNT_INTVAL },
322 { "LED Deck B: CUP/REL", 10 | CNT_INTVAL },
323 { "LED Deck B: PLAY", 9 | CNT_INTVAL },
324 { "LED Deck B: SYNC", 8 | CNT_INTVAL },
325};
326
276static int __devinit add_controls(struct caiaq_controller *c, int num, 327static int __devinit add_controls(struct caiaq_controller *c, int num,
277 struct snd_usb_caiaqdev *dev) 328 struct snd_usb_caiaqdev *dev)
278{ 329{
@@ -321,10 +372,16 @@ int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
321 ret = add_controls(a8dj_controller, 372 ret = add_controls(a8dj_controller,
322 ARRAY_SIZE(a8dj_controller), dev); 373 ARRAY_SIZE(a8dj_controller), dev);
323 break; 374 break;
375
324 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): 376 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
325 ret = add_controls(a4dj_controller, 377 ret = add_controls(a4dj_controller,
326 ARRAY_SIZE(a4dj_controller), dev); 378 ARRAY_SIZE(a4dj_controller), dev);
327 break; 379 break;
380
381 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
382 ret = add_controls(kontrolx1_controller,
383 ARRAY_SIZE(kontrolx1_controller), dev);
384 break;
328 } 385 }
329 386
330 return ret; 387 return ret;
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index a3f02dd97440..08ee2545830e 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -46,7 +46,8 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
46 "{Native Instruments, Audio 4 DJ}," 46 "{Native Instruments, Audio 4 DJ},"
47 "{Native Instruments, Audio 8 DJ}," 47 "{Native Instruments, Audio 8 DJ},"
48 "{Native Instruments, Session I/O}," 48 "{Native Instruments, Session I/O},"
49 "{Native Instruments, GuitarRig mobile}"); 49 "{Native Instruments, GuitarRig mobile}"
50 "{Native Instruments, Traktor Kontrol X1}");
50 51
51static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ 52static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
52static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ 53static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
@@ -127,6 +128,11 @@ static struct usb_device_id snd_usb_id_table[] = {
127 .idVendor = USB_VID_NATIVEINSTRUMENTS, 128 .idVendor = USB_VID_NATIVEINSTRUMENTS,
128 .idProduct = USB_PID_AUDIO2DJ 129 .idProduct = USB_PID_AUDIO2DJ
129 }, 130 },
131 {
132 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
133 .idVendor = USB_VID_NATIVEINSTRUMENTS,
134 .idProduct = USB_PID_TRAKTORKONTROLX1
135 },
130 { /* terminator */ } 136 { /* terminator */ }
131}; 137};
132 138
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index 44e3edf88bef..f1117ecc84fd 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -5,18 +5,20 @@
5 5
6#define USB_VID_NATIVEINSTRUMENTS 0x17cc 6#define USB_VID_NATIVEINSTRUMENTS 0x17cc
7 7
8#define USB_PID_RIGKONTROL2 0x1969 8#define USB_PID_RIGKONTROL2 0x1969
9#define USB_PID_RIGKONTROL3 0x1940 9#define USB_PID_RIGKONTROL3 0x1940
10#define USB_PID_KORECONTROLLER 0x4711 10#define USB_PID_KORECONTROLLER 0x4711
11#define USB_PID_KORECONTROLLER2 0x4712 11#define USB_PID_KORECONTROLLER2 0x4712
12#define USB_PID_AK1 0x0815 12#define USB_PID_AK1 0x0815
13#define USB_PID_AUDIO2DJ 0x041c 13#define USB_PID_AUDIO2DJ 0x041c
14#define USB_PID_AUDIO4DJ 0x0839 14#define USB_PID_AUDIO4DJ 0x0839
15#define USB_PID_AUDIO8DJ 0x1978 15#define USB_PID_AUDIO8DJ 0x1978
16#define USB_PID_SESSIONIO 0x1915 16#define USB_PID_SESSIONIO 0x1915
17#define USB_PID_GUITARRIGMOBILE 0x0d8d 17#define USB_PID_GUITARRIGMOBILE 0x0d8d
18#define USB_PID_TRAKTORKONTROLX1 0x2305
18 19
19#define EP1_BUFSIZE 64 20#define EP1_BUFSIZE 64
21#define EP4_BUFSIZE 512
20#define CAIAQ_USB_STR_LEN 0xff 22#define CAIAQ_USB_STR_LEN 0xff
21#define MAX_STREAMS 32 23#define MAX_STREAMS 32
22 24
@@ -104,6 +106,8 @@ struct snd_usb_caiaqdev {
104 struct input_dev *input_dev; 106 struct input_dev *input_dev;
105 char phys[64]; /* physical device path */ 107 char phys[64]; /* physical device path */
106 unsigned short keycode[64]; 108 unsigned short keycode[64];
109 struct urb *ep4_in_urb;
110 unsigned char ep4_in_buf[EP4_BUFSIZE];
107#endif 111#endif
108 112
109 /* ALSA */ 113 /* ALSA */
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index a48d309bd94c..27ed0bc651ae 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -19,6 +19,7 @@
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/usb.h> 20#include <linux/usb.h>
21#include <linux/usb/input.h> 21#include <linux/usb/input.h>
22#include <sound/core.h>
22#include <sound/pcm.h> 23#include <sound/pcm.h>
23 24
24#include "device.h" 25#include "device.h"
@@ -65,6 +66,8 @@ static unsigned short keycode_kore[] = {
65 KEY_BRL_DOT5 66 KEY_BRL_DOT5
66}; 67};
67 68
69#define KONTROLX1_INPUTS 40
70
68#define DEG90 (range / 2) 71#define DEG90 (range / 2)
69#define DEG180 (range) 72#define DEG180 (range)
70#define DEG270 (DEG90 + DEG180) 73#define DEG270 (DEG90 + DEG180)
@@ -162,6 +165,17 @@ static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
162 input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]); 165 input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
163 input_sync(input_dev); 166 input_sync(input_dev);
164 break; 167 break;
168 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
169 input_report_abs(input_dev, ABS_HAT0X, (buf[8] << 8) | buf[9]);
170 input_report_abs(input_dev, ABS_HAT0Y, (buf[4] << 8) | buf[5]);
171 input_report_abs(input_dev, ABS_HAT1X, (buf[12] << 8) | buf[13]);
172 input_report_abs(input_dev, ABS_HAT1Y, (buf[2] << 8) | buf[3]);
173 input_report_abs(input_dev, ABS_HAT2X, (buf[15] << 8) | buf[15]);
174 input_report_abs(input_dev, ABS_HAT2Y, (buf[0] << 8) | buf[1]);
175 input_report_abs(input_dev, ABS_HAT3X, (buf[10] << 8) | buf[11]);
176 input_report_abs(input_dev, ABS_HAT3Y, (buf[6] << 8) | buf[7]);
177 input_sync(input_dev);
178 break;
165 } 179 }
166} 180}
167 181
@@ -201,7 +215,7 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
201} 215}
202 216
203static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev, 217static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
204 char *buf, unsigned int len) 218 unsigned char *buf, unsigned int len)
205{ 219{
206 struct input_dev *input_dev = dev->input_dev; 220 struct input_dev *input_dev = dev->input_dev;
207 unsigned short *keycode = input_dev->keycode; 221 unsigned short *keycode = input_dev->keycode;
@@ -218,15 +232,84 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
218 input_report_key(input_dev, keycode[i], 232 input_report_key(input_dev, keycode[i],
219 buf[i / 8] & (1 << (i % 8))); 233 buf[i / 8] & (1 << (i % 8)));
220 234
221 if (dev->chip.usb_id == 235 switch (dev->chip.usb_id) {
222 USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER) || 236 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
223 dev->chip.usb_id == 237 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
224 USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2))
225 input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]); 238 input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]);
239 break;
240 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
241 /* rotary encoders */
242 input_report_abs(dev->input_dev, ABS_X, buf[5] & 0xf);
243 input_report_abs(dev->input_dev, ABS_Y, buf[5] >> 4);
244 input_report_abs(dev->input_dev, ABS_Z, buf[6] & 0xf);
245 input_report_abs(dev->input_dev, ABS_MISC, buf[6] >> 4);
246 break;
247 }
226 248
227 input_sync(input_dev); 249 input_sync(input_dev);
228} 250}
229 251
252static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
253{
254 struct snd_usb_caiaqdev *dev = urb->context;
255 unsigned char *buf = urb->transfer_buffer;
256 int ret;
257
258 if (urb->status || !dev || urb != dev->ep4_in_urb)
259 return;
260
261 if (urb->actual_length < 24)
262 goto requeue;
263
264 switch (dev->chip.usb_id) {
265 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
266 if (buf[0] & 0x3)
267 snd_caiaq_input_read_io(dev, buf + 1, 7);
268
269 if (buf[0] & 0x4)
270 snd_caiaq_input_read_analog(dev, buf + 8, 16);
271
272 break;
273 }
274
275requeue:
276 dev->ep4_in_urb->actual_length = 0;
277 ret = usb_submit_urb(dev->ep4_in_urb, GFP_ATOMIC);
278 if (ret < 0)
279 log("unable to submit urb. OOM!?\n");
280}
281
282static int snd_usb_caiaq_input_open(struct input_dev *idev)
283{
284 struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
285
286 if (!dev)
287 return -EINVAL;
288
289 switch (dev->chip.usb_id) {
290 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
291 if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
292 return -EIO;
293 break;
294 }
295
296 return 0;
297}
298
299static void snd_usb_caiaq_input_close(struct input_dev *idev)
300{
301 struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
302
303 if (!dev)
304 return;
305
306 switch (dev->chip.usb_id) {
307 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
308 usb_kill_urb(dev->ep4_in_urb);
309 break;
310 }
311}
312
230void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, 313void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev,
231 char *buf, 314 char *buf,
232 unsigned int len) 315 unsigned int len)
@@ -251,7 +334,7 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
251{ 334{
252 struct usb_device *usb_dev = dev->chip.dev; 335 struct usb_device *usb_dev = dev->chip.dev;
253 struct input_dev *input; 336 struct input_dev *input;
254 int i, ret; 337 int i, ret = 0;
255 338
256 input = input_allocate_device(); 339 input = input_allocate_device();
257 if (!input) 340 if (!input)
@@ -265,7 +348,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
265 usb_to_input_id(usb_dev, &input->id); 348 usb_to_input_id(usb_dev, &input->id);
266 input->dev.parent = &usb_dev->dev; 349 input->dev.parent = &usb_dev->dev;
267 350
268 switch (dev->chip.usb_id) { 351 input_set_drvdata(input, dev);
352
353 switch (dev->chip.usb_id) {
269 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): 354 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
270 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 355 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
271 input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | 356 input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
@@ -326,25 +411,72 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
326 input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1); 411 input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1);
327 snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5); 412 snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
328 break; 413 break;
414 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
415 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
416 input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
417 BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) |
418 BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) |
419 BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) |
420 BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
421 BIT_MASK(ABS_Z);
422 input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
423 BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLX1_INPUTS);
424 for (i = 0; i < KONTROLX1_INPUTS; i++)
425 dev->keycode[i] = BTN_MISC + i;
426 input->keycodemax = KONTROLX1_INPUTS;
427
428 /* analog potentiometers */
429 input_set_abs_params(input, ABS_HAT0X, 0, 4096, 0, 10);
430 input_set_abs_params(input, ABS_HAT0Y, 0, 4096, 0, 10);
431 input_set_abs_params(input, ABS_HAT1X, 0, 4096, 0, 10);
432 input_set_abs_params(input, ABS_HAT1Y, 0, 4096, 0, 10);
433 input_set_abs_params(input, ABS_HAT2X, 0, 4096, 0, 10);
434 input_set_abs_params(input, ABS_HAT2Y, 0, 4096, 0, 10);
435 input_set_abs_params(input, ABS_HAT3X, 0, 4096, 0, 10);
436 input_set_abs_params(input, ABS_HAT3Y, 0, 4096, 0, 10);
437
438 /* rotary encoders */
439 input_set_abs_params(input, ABS_X, 0, 0xf, 0, 1);
440 input_set_abs_params(input, ABS_Y, 0, 0xf, 0, 1);
441 input_set_abs_params(input, ABS_Z, 0, 0xf, 0, 1);
442 input_set_abs_params(input, ABS_MISC, 0, 0xf, 0, 1);
443
444 dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
445 if (!dev->ep4_in_urb) {
446 ret = -ENOMEM;
447 goto exit_free_idev;
448 }
449
450 usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
451 usb_rcvbulkpipe(usb_dev, 0x4),
452 dev->ep4_in_buf, EP4_BUFSIZE,
453 snd_usb_caiaq_ep4_reply_dispatch, dev);
454
455 snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
456
457 break;
329 default: 458 default:
330 /* no input methods supported on this device */ 459 /* no input methods supported on this device */
331 input_free_device(input); 460 goto exit_free_idev;
332 return 0;
333 } 461 }
334 462
463 input->open = snd_usb_caiaq_input_open;
464 input->close = snd_usb_caiaq_input_close;
335 input->keycode = dev->keycode; 465 input->keycode = dev->keycode;
336 input->keycodesize = sizeof(unsigned short); 466 input->keycodesize = sizeof(unsigned short);
337 for (i = 0; i < input->keycodemax; i++) 467 for (i = 0; i < input->keycodemax; i++)
338 __set_bit(dev->keycode[i], input->keybit); 468 __set_bit(dev->keycode[i], input->keybit);
339 469
340 ret = input_register_device(input); 470 ret = input_register_device(input);
341 if (ret < 0) { 471 if (ret < 0)
342 input_free_device(input); 472 goto exit_free_idev;
343 return ret;
344 }
345 473
346 dev->input_dev = input; 474 dev->input_dev = input;
347 return 0; 475 return 0;
476
477exit_free_idev:
478 input_free_device(input);
479 return ret;
348} 480}
349 481
350void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev) 482void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
@@ -352,6 +484,10 @@ void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
352 if (!dev || !dev->input_dev) 484 if (!dev || !dev->input_dev)
353 return; 485 return;
354 486
487 usb_kill_urb(dev->ep4_in_urb);
488 usb_free_urb(dev->ep4_in_urb);
489 dev->ep4_in_urb = NULL;
490
355 input_unregister_device(dev->input_dev); 491 input_unregister_device(dev->input_dev);
356 dev->input_dev = NULL; 492 dev->input_dev = NULL;
357} 493}