mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 00:39:48 +00:00
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>
This commit is contained in:
parent
fc8aa7b16a
commit
6da7a2aa89
5 changed files with 249 additions and 45 deletions
|
@ -65,6 +65,7 @@ config SND_USB_CAIAQ
|
||||||
* Native Instruments Audio 8 DJ
|
* Native Instruments Audio 8 DJ
|
||||||
* Native Instruments Guitar Rig Session I/O
|
* Native Instruments Guitar Rig Session I/O
|
||||||
* Native Instruments Guitar Rig mobile
|
* Native Instruments Guitar Rig mobile
|
||||||
|
* Native Instruments Traktor Kontrol X1
|
||||||
|
|
||||||
To compile this driver as a module, choose M here: the module
|
To compile this driver as a module, choose M here: the module
|
||||||
will be called snd-usb-caiaq.
|
will be called snd-usb-caiaq.
|
||||||
|
|
|
@ -35,33 +35,41 @@ static int control_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
|
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
|
||||||
int pos = kcontrol->private_value;
|
int pos = kcontrol->private_value;
|
||||||
int is_intval = pos & CNT_INTVAL;
|
int is_intval = pos & CNT_INTVAL;
|
||||||
unsigned int id = dev->chip.usb_id;
|
int maxval = 63;
|
||||||
|
|
||||||
uinfo->count = 1;
|
uinfo->count = 1;
|
||||||
pos &= ~CNT_INTVAL;
|
pos &= ~CNT_INTVAL;
|
||||||
|
|
||||||
if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)
|
switch (dev->chip.usb_id) {
|
||||||
&& (pos == 0)) {
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
|
||||||
|
if (pos == 0) {
|
||||||
/* current input mode of A8DJ */
|
/* current input mode of A8DJ */
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||||
uinfo->value.integer.min = 0;
|
uinfo->value.integer.min = 0;
|
||||||
uinfo->value.integer.max = 2;
|
uinfo->value.integer.max = 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
|
||||||
&& (pos == 0)) {
|
if (pos == 0) {
|
||||||
/* current input mode of A4DJ */
|
/* current input mode of A4DJ */
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||||
uinfo->value.integer.min = 0;
|
uinfo->value.integer.min = 0;
|
||||||
uinfo->value.integer.max = 1;
|
uinfo->value.integer.max = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
|
maxval = 127;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_intval) {
|
if (is_intval) {
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||||
uinfo->value.integer.min = 0;
|
uinfo->value.integer.min = 0;
|
||||||
uinfo->value.integer.max = 64;
|
uinfo->value.integer.max = maxval;
|
||||||
} else {
|
} else {
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
|
||||||
uinfo->value.integer.min = 0;
|
uinfo->value.integer.min = 0;
|
||||||
|
@ -102,9 +110,10 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
|
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
|
||||||
int pos = kcontrol->private_value;
|
int pos = kcontrol->private_value;
|
||||||
|
unsigned char cmd = EP1_CMD_WRITE_IO;
|
||||||
|
|
||||||
if (dev->chip.usb_id ==
|
switch (dev->chip.usb_id) {
|
||||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) {
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): {
|
||||||
/* A4DJ has only one control */
|
/* A4DJ has only one control */
|
||||||
/* do not expose hardware input mode 0 */
|
/* do not expose hardware input mode 0 */
|
||||||
dev->control_state[0] = ucontrol->value.integer.value[0] + 1;
|
dev->control_state[0] = ucontrol->value.integer.value[0] + 1;
|
||||||
|
@ -113,10 +122,15 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
|
cmd = EP1_CMD_DIMM_LEDS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (pos & CNT_INTVAL) {
|
if (pos & CNT_INTVAL) {
|
||||||
dev->control_state[pos & ~CNT_INTVAL]
|
dev->control_state[pos & ~CNT_INTVAL]
|
||||||
= ucontrol->value.integer.value[0];
|
= ucontrol->value.integer.value[0];
|
||||||
snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
|
snd_usb_caiaq_send_command(dev, cmd,
|
||||||
dev->control_state, sizeof(dev->control_state));
|
dev->control_state, sizeof(dev->control_state));
|
||||||
} else {
|
} else {
|
||||||
if (ucontrol->value.integer.value[0])
|
if (ucontrol->value.integer.value[0])
|
||||||
|
@ -124,7 +138,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
||||||
else
|
else
|
||||||
dev->control_state[pos / 8] &= ~(1 << (pos % 8));
|
dev->control_state[pos / 8] &= ~(1 << (pos % 8));
|
||||||
|
|
||||||
snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
|
snd_usb_caiaq_send_command(dev, cmd,
|
||||||
dev->control_state, sizeof(dev->control_state));
|
dev->control_state, sizeof(dev->control_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +287,43 @@ static struct caiaq_controller a4dj_controller[] = {
|
||||||
{ "Current input mode", 0 | CNT_INTVAL }
|
{ "Current input mode", 0 | CNT_INTVAL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct caiaq_controller kontrolx1_controller[] = {
|
||||||
|
{ "LED FX A: ON", 7 | CNT_INTVAL },
|
||||||
|
{ "LED FX A: 1", 6 | CNT_INTVAL },
|
||||||
|
{ "LED FX A: 2", 5 | CNT_INTVAL },
|
||||||
|
{ "LED FX A: 3", 4 | CNT_INTVAL },
|
||||||
|
{ "LED FX B: ON", 3 | CNT_INTVAL },
|
||||||
|
{ "LED FX B: 1", 2 | CNT_INTVAL },
|
||||||
|
{ "LED FX B: 2", 1 | CNT_INTVAL },
|
||||||
|
{ "LED FX B: 3", 0 | CNT_INTVAL },
|
||||||
|
|
||||||
|
{ "LED Hotcue", 28 | CNT_INTVAL },
|
||||||
|
{ "LED Shift (white)", 29 | CNT_INTVAL },
|
||||||
|
{ "LED Shift (green)", 30 | CNT_INTVAL },
|
||||||
|
|
||||||
|
{ "LED Deck A: FX1", 24 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: FX2", 25 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: IN", 17 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: OUT", 16 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: < BEAT", 19 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: BEAT >", 18 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: CUE/ABS", 21 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: CUP/REL", 20 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: PLAY", 23 | CNT_INTVAL },
|
||||||
|
{ "LED Deck A: SYNC", 22 | CNT_INTVAL },
|
||||||
|
|
||||||
|
{ "LED Deck B: FX1", 26 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: FX2", 27 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: IN", 15 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: OUT", 14 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: < BEAT", 13 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: BEAT >", 12 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: CUE/ABS", 11 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: CUP/REL", 10 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: PLAY", 9 | CNT_INTVAL },
|
||||||
|
{ "LED Deck B: SYNC", 8 | CNT_INTVAL },
|
||||||
|
};
|
||||||
|
|
||||||
static int __devinit add_controls(struct caiaq_controller *c, int num,
|
static int __devinit add_controls(struct caiaq_controller *c, int num,
|
||||||
struct snd_usb_caiaqdev *dev)
|
struct snd_usb_caiaqdev *dev)
|
||||||
{
|
{
|
||||||
|
@ -321,10 +372,16 @@ int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
|
||||||
ret = add_controls(a8dj_controller,
|
ret = add_controls(a8dj_controller,
|
||||||
ARRAY_SIZE(a8dj_controller), dev);
|
ARRAY_SIZE(a8dj_controller), dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
|
||||||
ret = add_controls(a4dj_controller,
|
ret = add_controls(a4dj_controller,
|
||||||
ARRAY_SIZE(a4dj_controller), dev);
|
ARRAY_SIZE(a4dj_controller), dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
|
ret = add_controls(kontrolx1_controller,
|
||||||
|
ARRAY_SIZE(kontrolx1_controller), dev);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -46,7 +46,8 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
|
||||||
"{Native Instruments, Audio 4 DJ},"
|
"{Native Instruments, Audio 4 DJ},"
|
||||||
"{Native Instruments, Audio 8 DJ},"
|
"{Native Instruments, Audio 8 DJ},"
|
||||||
"{Native Instruments, Session I/O},"
|
"{Native Instruments, Session I/O},"
|
||||||
"{Native Instruments, GuitarRig mobile}");
|
"{Native Instruments, GuitarRig mobile}"
|
||||||
|
"{Native Instruments, Traktor Kontrol X1}");
|
||||||
|
|
||||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
|
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
|
||||||
static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
|
static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
|
||||||
|
@ -127,6 +128,11 @@ static struct usb_device_id snd_usb_id_table[] = {
|
||||||
.idVendor = USB_VID_NATIVEINSTRUMENTS,
|
.idVendor = USB_VID_NATIVEINSTRUMENTS,
|
||||||
.idProduct = USB_PID_AUDIO2DJ
|
.idProduct = USB_PID_AUDIO2DJ
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
|
||||||
|
.idVendor = USB_VID_NATIVEINSTRUMENTS,
|
||||||
|
.idProduct = USB_PID_TRAKTORKONTROLX1
|
||||||
|
},
|
||||||
{ /* terminator */ }
|
{ /* terminator */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
#define USB_PID_AUDIO8DJ 0x1978
|
#define USB_PID_AUDIO8DJ 0x1978
|
||||||
#define USB_PID_SESSIONIO 0x1915
|
#define USB_PID_SESSIONIO 0x1915
|
||||||
#define USB_PID_GUITARRIGMOBILE 0x0d8d
|
#define USB_PID_GUITARRIGMOBILE 0x0d8d
|
||||||
|
#define USB_PID_TRAKTORKONTROLX1 0x2305
|
||||||
|
|
||||||
#define EP1_BUFSIZE 64
|
#define EP1_BUFSIZE 64
|
||||||
|
#define EP4_BUFSIZE 512
|
||||||
#define CAIAQ_USB_STR_LEN 0xff
|
#define CAIAQ_USB_STR_LEN 0xff
|
||||||
#define MAX_STREAMS 32
|
#define MAX_STREAMS 32
|
||||||
|
|
||||||
|
@ -104,6 +106,8 @@ struct snd_usb_caiaqdev {
|
||||||
struct input_dev *input_dev;
|
struct input_dev *input_dev;
|
||||||
char phys[64]; /* physical device path */
|
char phys[64]; /* physical device path */
|
||||||
unsigned short keycode[64];
|
unsigned short keycode[64];
|
||||||
|
struct urb *ep4_in_urb;
|
||||||
|
unsigned char ep4_in_buf[EP4_BUFSIZE];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ALSA */
|
/* ALSA */
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <linux/usb/input.h>
|
#include <linux/usb/input.h>
|
||||||
|
#include <sound/core.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
@ -65,6 +66,8 @@ static unsigned short keycode_kore[] = {
|
||||||
KEY_BRL_DOT5
|
KEY_BRL_DOT5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define KONTROLX1_INPUTS 40
|
||||||
|
|
||||||
#define DEG90 (range / 2)
|
#define DEG90 (range / 2)
|
||||||
#define DEG180 (range)
|
#define DEG180 (range)
|
||||||
#define DEG270 (DEG90 + DEG180)
|
#define DEG270 (DEG90 + DEG180)
|
||||||
|
@ -162,6 +165,17 @@ static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
|
||||||
input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
|
input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
|
||||||
input_sync(input_dev);
|
input_sync(input_dev);
|
||||||
break;
|
break;
|
||||||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
|
input_report_abs(input_dev, ABS_HAT0X, (buf[8] << 8) | buf[9]);
|
||||||
|
input_report_abs(input_dev, ABS_HAT0Y, (buf[4] << 8) | buf[5]);
|
||||||
|
input_report_abs(input_dev, ABS_HAT1X, (buf[12] << 8) | buf[13]);
|
||||||
|
input_report_abs(input_dev, ABS_HAT1Y, (buf[2] << 8) | buf[3]);
|
||||||
|
input_report_abs(input_dev, ABS_HAT2X, (buf[15] << 8) | buf[15]);
|
||||||
|
input_report_abs(input_dev, ABS_HAT2Y, (buf[0] << 8) | buf[1]);
|
||||||
|
input_report_abs(input_dev, ABS_HAT3X, (buf[10] << 8) | buf[11]);
|
||||||
|
input_report_abs(input_dev, ABS_HAT3Y, (buf[6] << 8) | buf[7]);
|
||||||
|
input_sync(input_dev);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +215,7 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
|
static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
|
||||||
char *buf, unsigned int len)
|
unsigned char *buf, unsigned int len)
|
||||||
{
|
{
|
||||||
struct input_dev *input_dev = dev->input_dev;
|
struct input_dev *input_dev = dev->input_dev;
|
||||||
unsigned short *keycode = input_dev->keycode;
|
unsigned short *keycode = input_dev->keycode;
|
||||||
|
@ -218,15 +232,84 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
|
||||||
input_report_key(input_dev, keycode[i],
|
input_report_key(input_dev, keycode[i],
|
||||||
buf[i / 8] & (1 << (i % 8)));
|
buf[i / 8] & (1 << (i % 8)));
|
||||||
|
|
||||||
if (dev->chip.usb_id ==
|
switch (dev->chip.usb_id) {
|
||||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER) ||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
|
||||||
dev->chip.usb_id ==
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
|
||||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2))
|
|
||||||
input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]);
|
input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]);
|
||||||
|
break;
|
||||||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
|
/* rotary encoders */
|
||||||
|
input_report_abs(dev->input_dev, ABS_X, buf[5] & 0xf);
|
||||||
|
input_report_abs(dev->input_dev, ABS_Y, buf[5] >> 4);
|
||||||
|
input_report_abs(dev->input_dev, ABS_Z, buf[6] & 0xf);
|
||||||
|
input_report_abs(dev->input_dev, ABS_MISC, buf[6] >> 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
input_sync(input_dev);
|
input_sync(input_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
|
||||||
|
{
|
||||||
|
struct snd_usb_caiaqdev *dev = urb->context;
|
||||||
|
unsigned char *buf = urb->transfer_buffer;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (urb->status || !dev || urb != dev->ep4_in_urb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (urb->actual_length < 24)
|
||||||
|
goto requeue;
|
||||||
|
|
||||||
|
switch (dev->chip.usb_id) {
|
||||||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
|
if (buf[0] & 0x3)
|
||||||
|
snd_caiaq_input_read_io(dev, buf + 1, 7);
|
||||||
|
|
||||||
|
if (buf[0] & 0x4)
|
||||||
|
snd_caiaq_input_read_analog(dev, buf + 8, 16);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
requeue:
|
||||||
|
dev->ep4_in_urb->actual_length = 0;
|
||||||
|
ret = usb_submit_urb(dev->ep4_in_urb, GFP_ATOMIC);
|
||||||
|
if (ret < 0)
|
||||||
|
log("unable to submit urb. OOM!?\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_usb_caiaq_input_open(struct input_dev *idev)
|
||||||
|
{
|
||||||
|
struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (dev->chip.usb_id) {
|
||||||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
|
if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
|
||||||
|
return -EIO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void snd_usb_caiaq_input_close(struct input_dev *idev)
|
||||||
|
{
|
||||||
|
struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (dev->chip.usb_id) {
|
||||||
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
|
usb_kill_urb(dev->ep4_in_urb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev,
|
void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev,
|
||||||
char *buf,
|
char *buf,
|
||||||
unsigned int len)
|
unsigned int len)
|
||||||
|
@ -251,7 +334,7 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
|
||||||
{
|
{
|
||||||
struct usb_device *usb_dev = dev->chip.dev;
|
struct usb_device *usb_dev = dev->chip.dev;
|
||||||
struct input_dev *input;
|
struct input_dev *input;
|
||||||
int i, ret;
|
int i, ret = 0;
|
||||||
|
|
||||||
input = input_allocate_device();
|
input = input_allocate_device();
|
||||||
if (!input)
|
if (!input)
|
||||||
|
@ -265,6 +348,8 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
|
||||||
usb_to_input_id(usb_dev, &input->id);
|
usb_to_input_id(usb_dev, &input->id);
|
||||||
input->dev.parent = &usb_dev->dev;
|
input->dev.parent = &usb_dev->dev;
|
||||||
|
|
||||||
|
input_set_drvdata(input, dev);
|
||||||
|
|
||||||
switch (dev->chip.usb_id) {
|
switch (dev->chip.usb_id) {
|
||||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
|
||||||
input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||||
|
@ -326,25 +411,72 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
|
||||||
input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1);
|
input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1);
|
||||||
snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
|
snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
|
||||||
break;
|
break;
|
||||||
default:
|
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||||
/* no input methods supported on this device */
|
input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||||
input_free_device(input);
|
input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
|
||||||
return 0;
|
BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) |
|
||||||
|
BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) |
|
||||||
|
BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) |
|
||||||
|
BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
|
||||||
|
BIT_MASK(ABS_Z);
|
||||||
|
input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
|
||||||
|
BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLX1_INPUTS);
|
||||||
|
for (i = 0; i < KONTROLX1_INPUTS; i++)
|
||||||
|
dev->keycode[i] = BTN_MISC + i;
|
||||||
|
input->keycodemax = KONTROLX1_INPUTS;
|
||||||
|
|
||||||
|
/* analog potentiometers */
|
||||||
|
input_set_abs_params(input, ABS_HAT0X, 0, 4096, 0, 10);
|
||||||
|
input_set_abs_params(input, ABS_HAT0Y, 0, 4096, 0, 10);
|
||||||
|
input_set_abs_params(input, ABS_HAT1X, 0, 4096, 0, 10);
|
||||||
|
input_set_abs_params(input, ABS_HAT1Y, 0, 4096, 0, 10);
|
||||||
|
input_set_abs_params(input, ABS_HAT2X, 0, 4096, 0, 10);
|
||||||
|
input_set_abs_params(input, ABS_HAT2Y, 0, 4096, 0, 10);
|
||||||
|
input_set_abs_params(input, ABS_HAT3X, 0, 4096, 0, 10);
|
||||||
|
input_set_abs_params(input, ABS_HAT3Y, 0, 4096, 0, 10);
|
||||||
|
|
||||||
|
/* rotary encoders */
|
||||||
|
input_set_abs_params(input, ABS_X, 0, 0xf, 0, 1);
|
||||||
|
input_set_abs_params(input, ABS_Y, 0, 0xf, 0, 1);
|
||||||
|
input_set_abs_params(input, ABS_Z, 0, 0xf, 0, 1);
|
||||||
|
input_set_abs_params(input, ABS_MISC, 0, 0xf, 0, 1);
|
||||||
|
|
||||||
|
dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
|
if (!dev->ep4_in_urb) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto exit_free_idev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
|
||||||
|
usb_rcvbulkpipe(usb_dev, 0x4),
|
||||||
|
dev->ep4_in_buf, EP4_BUFSIZE,
|
||||||
|
snd_usb_caiaq_ep4_reply_dispatch, dev);
|
||||||
|
|
||||||
|
snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* no input methods supported on this device */
|
||||||
|
goto exit_free_idev;
|
||||||
|
}
|
||||||
|
|
||||||
|
input->open = snd_usb_caiaq_input_open;
|
||||||
|
input->close = snd_usb_caiaq_input_close;
|
||||||
input->keycode = dev->keycode;
|
input->keycode = dev->keycode;
|
||||||
input->keycodesize = sizeof(unsigned short);
|
input->keycodesize = sizeof(unsigned short);
|
||||||
for (i = 0; i < input->keycodemax; i++)
|
for (i = 0; i < input->keycodemax; i++)
|
||||||
__set_bit(dev->keycode[i], input->keybit);
|
__set_bit(dev->keycode[i], input->keybit);
|
||||||
|
|
||||||
ret = input_register_device(input);
|
ret = input_register_device(input);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
input_free_device(input);
|
goto exit_free_idev;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->input_dev = input;
|
dev->input_dev = input;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
exit_free_idev:
|
||||||
|
input_free_device(input);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
|
void 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)
|
||||||
if (!dev || !dev->input_dev)
|
if (!dev || !dev->input_dev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
usb_kill_urb(dev->ep4_in_urb);
|
||||||
|
usb_free_urb(dev->ep4_in_urb);
|
||||||
|
dev->ep4_in_urb = NULL;
|
||||||
|
|
||||||
input_unregister_device(dev->input_dev);
|
input_unregister_device(dev->input_dev);
|
||||||
dev->input_dev = NULL;
|
dev->input_dev = NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue