2007-03-26 19:11:24 +02:00
/*
* Copyright ( c ) 2006 , 2007 Daniel Mack , Tim Ruetz
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/init.h>
# include <linux/usb.h>
2007-11-21 16:45:23 +01:00
# include <linux/usb/input.h>
2007-03-26 19:11:24 +02:00
# include <sound/pcm.h>
2009-04-01 19:05:39 +02:00
# include "device.h"
# include "input.h"
2007-03-26 19:11:24 +02:00
2007-11-21 16:45:23 +01:00
static unsigned short keycode_ak1 [ ] = { KEY_C , KEY_B , KEY_A } ;
static unsigned short keycode_rk2 [ ] = { KEY_1 , KEY_2 , KEY_3 , KEY_4 ,
KEY_5 , KEY_6 , KEY_7 } ;
static unsigned short keycode_rk3 [ ] = { KEY_1 , KEY_2 , KEY_3 , KEY_4 ,
KEY_5 , KEY_6 , KEY_7 , KEY_5 , KEY_6 } ;
2007-03-26 19:11:24 +02:00
2007-11-22 11:40:04 +01:00
static unsigned short keycode_kore [ ] = {
KEY_FN_F1 , /* "menu" */
KEY_FN_F7 , /* "lcd backlight */
KEY_FN_F2 , /* "control" */
KEY_FN_F3 , /* "enter" */
KEY_FN_F4 , /* "view" */
KEY_FN_F5 , /* "esc" */
KEY_FN_F6 , /* "sound" */
KEY_FN_F8 , /* array spacer, never triggered. */
KEY_RIGHT ,
KEY_DOWN ,
KEY_UP ,
KEY_LEFT ,
KEY_SOUND , /* "listen" */
KEY_RECORD ,
KEY_PLAYPAUSE ,
KEY_STOP ,
BTN_4 , /* 8 softkeys */
BTN_3 ,
BTN_2 ,
BTN_1 ,
BTN_8 ,
BTN_7 ,
BTN_6 ,
BTN_5 ,
KEY_BRL_DOT4 , /* touch sensitive knobs */
KEY_BRL_DOT3 ,
KEY_BRL_DOT2 ,
KEY_BRL_DOT1 ,
KEY_BRL_DOT8 ,
KEY_BRL_DOT7 ,
KEY_BRL_DOT6 ,
KEY_BRL_DOT5
} ;
2007-11-21 16:45:23 +01:00
# define DEG90 (range / 2)
# define DEG180 (range)
# define DEG270 (DEG90 + DEG180)
# define DEG360 (DEG180 * 2)
# define HIGH_PEAK (268)
# define LOW_PEAK (-7)
2007-03-26 19:11:24 +02:00
/* some of these devices have endless rotation potentiometers
* built in which use two tapers , 90 degrees phase shifted .
* this algorithm decodes them to one single value , ranging
* from 0 to 999 */
static unsigned int decode_erp ( unsigned char a , unsigned char b )
{
int weight_a , weight_b ;
int pos_a , pos_b ;
int ret ;
int range = HIGH_PEAK - LOW_PEAK ;
int mid_value = ( HIGH_PEAK + LOW_PEAK ) / 2 ;
2007-11-21 16:45:23 +01:00
weight_b = abs ( mid_value - a ) - ( range / 2 - 100 ) / 2 ;
2007-03-26 19:11:24 +02:00
if ( weight_b < 0 )
weight_b = 0 ;
if ( weight_b > 100 )
weight_b = 100 ;
weight_a = 100 - weight_b ;
if ( a < mid_value ) {
/* 0..90 and 270..360 degrees */
pos_b = b - LOW_PEAK + DEG270 ;
if ( pos_b > = DEG360 )
pos_b - = DEG360 ;
} else
/* 90..270 degrees */
pos_b = HIGH_PEAK - b + DEG90 ;
if ( b > mid_value )
/* 0..180 degrees */
pos_a = a - LOW_PEAK ;
else
/* 180..360 degrees */
pos_a = HIGH_PEAK - a + DEG180 ;
/* interpolate both slider values, depending on weight factors */
/* 0..99 x DEG360 */
ret = pos_a * weight_a + pos_b * weight_b ;
/* normalize to 0..999 */
ret * = 10 ;
ret / = DEG360 ;
if ( ret < 0 )
ret + = 1000 ;
2007-11-21 16:45:23 +01:00
2007-03-26 19:11:24 +02:00
if ( ret > = 1000 )
ret - = 1000 ;
return ret ;
}
# undef DEG90
# undef DEG180
# undef DEG270
# undef DEG360
# undef HIGH_PEAK
# undef LOW_PEAK
2007-11-21 16:45:23 +01:00
static void snd_caiaq_input_read_analog ( struct snd_usb_caiaqdev * dev ,
2007-09-17 14:45:14 +02:00
const unsigned char * buf ,
unsigned int len )
2007-03-26 19:11:24 +02:00
{
2007-11-21 16:45:23 +01:00
struct input_dev * input_dev = dev - > input_dev ;
2007-11-22 11:40:04 +01:00
switch ( dev - > chip . usb_id ) {
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_RIGKONTROL2 ) :
2007-11-21 16:45:23 +01:00
input_report_abs ( input_dev , ABS_X , ( buf [ 4 ] < < 8 ) | buf [ 5 ] ) ;
input_report_abs ( input_dev , ABS_Y , ( buf [ 0 ] < < 8 ) | buf [ 1 ] ) ;
input_report_abs ( input_dev , ABS_Z , ( buf [ 2 ] < < 8 ) | buf [ 3 ] ) ;
input_sync ( input_dev ) ;
2007-03-26 19:11:24 +02:00
break ;
2007-11-22 11:40:04 +01:00
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_RIGKONTROL3 ) :
input_report_abs ( input_dev , ABS_X , ( buf [ 0 ] < < 8 ) | buf [ 1 ] ) ;
input_report_abs ( input_dev , ABS_Y , ( buf [ 2 ] < < 8 ) | buf [ 3 ] ) ;
input_report_abs ( input_dev , ABS_Z , ( buf [ 4 ] < < 8 ) | buf [ 5 ] ) ;
input_sync ( input_dev ) ;
break ;
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_KORECONTROLLER ) :
2007-11-26 09:00:56 +01:00
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_KORECONTROLLER2 ) :
2007-11-21 16:45:23 +01:00
input_report_abs ( input_dev , ABS_X , ( buf [ 0 ] < < 8 ) | buf [ 1 ] ) ;
input_report_abs ( input_dev , ABS_Y , ( buf [ 2 ] < < 8 ) | buf [ 3 ] ) ;
input_report_abs ( input_dev , ABS_Z , ( buf [ 4 ] < < 8 ) | buf [ 5 ] ) ;
input_sync ( input_dev ) ;
2007-09-17 14:45:14 +02:00
break ;
2007-03-26 19:11:24 +02:00
}
}
2007-11-21 16:45:23 +01:00
static void snd_caiaq_input_read_erp ( struct snd_usb_caiaqdev * dev ,
2007-03-26 19:11:24 +02:00
const char * buf , unsigned int len )
{
2007-11-21 16:45:23 +01:00
struct input_dev * input_dev = dev - > input_dev ;
2007-03-26 19:11:24 +02:00
int i ;
2007-11-22 11:40:04 +01:00
switch ( dev - > chip . usb_id ) {
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_AK1 ) :
2007-03-26 19:11:24 +02:00
i = decode_erp ( buf [ 0 ] , buf [ 1 ] ) ;
2007-11-21 16:45:23 +01:00
input_report_abs ( input_dev , ABS_X , i ) ;
input_sync ( input_dev ) ;
2007-03-26 19:11:24 +02:00
break ;
2007-11-22 11:40:04 +01:00
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_KORECONTROLLER ) :
2007-11-26 09:00:56 +01:00
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_KORECONTROLLER2 ) :
2007-11-22 11:40:04 +01:00
i = decode_erp ( buf [ 7 ] , buf [ 5 ] ) ;
input_report_abs ( input_dev , ABS_HAT0X , i ) ;
i = decode_erp ( buf [ 12 ] , buf [ 14 ] ) ;
input_report_abs ( input_dev , ABS_HAT0Y , i ) ;
i = decode_erp ( buf [ 15 ] , buf [ 13 ] ) ;
input_report_abs ( input_dev , ABS_HAT1X , i ) ;
i = decode_erp ( buf [ 0 ] , buf [ 2 ] ) ;
input_report_abs ( input_dev , ABS_HAT1Y , i ) ;
i = decode_erp ( buf [ 3 ] , buf [ 1 ] ) ;
input_report_abs ( input_dev , ABS_HAT2X , i ) ;
i = decode_erp ( buf [ 8 ] , buf [ 10 ] ) ;
input_report_abs ( input_dev , ABS_HAT2Y , i ) ;
i = decode_erp ( buf [ 11 ] , buf [ 9 ] ) ;
input_report_abs ( input_dev , ABS_HAT3X , i ) ;
i = decode_erp ( buf [ 4 ] , buf [ 6 ] ) ;
input_report_abs ( input_dev , ABS_HAT3Y , i ) ;
input_sync ( input_dev ) ;
break ;
2007-03-26 19:11:24 +02:00
}
}
2007-11-21 16:45:23 +01:00
static void snd_caiaq_input_read_io ( struct snd_usb_caiaqdev * dev ,
2007-03-26 19:11:24 +02:00
char * buf , unsigned int len )
{
2007-11-21 16:45:23 +01:00
struct input_dev * input_dev = dev - > input_dev ;
unsigned short * keycode = input_dev - > keycode ;
2007-03-26 19:11:24 +02:00
int i ;
if ( ! keycode )
return ;
2007-11-21 16:45:23 +01:00
if ( input_dev - > id . product = = USB_PID_RIGKONTROL2 )
for ( i = 0 ; i < len ; i + + )
2007-03-26 19:11:24 +02:00
buf [ i ] = ~ buf [ i ] ;
2007-11-22 11:40:04 +01:00
for ( i = 0 ; i < input_dev - > keycodemax & & i < len * 8 ; i + + )
2007-11-21 16:45:23 +01:00
input_report_key ( input_dev , keycode [ i ] ,
buf [ i / 8 ] & ( 1 < < ( i % 8 ) ) ) ;
2007-03-26 19:11:24 +02:00
2007-11-22 11:40:04 +01:00
if ( dev - > chip . usb_id = =
2007-11-26 09:00:56 +01:00
USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_KORECONTROLLER ) | |
dev - > chip . usb_id = =
USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_KORECONTROLLER2 ) )
2007-11-22 11:40:04 +01:00
input_report_abs ( dev - > input_dev , ABS_MISC , 255 - buf [ 4 ] ) ;
2007-11-21 16:45:23 +01:00
input_sync ( input_dev ) ;
2007-03-26 19:11:24 +02:00
}
2007-11-21 16:45:23 +01:00
void snd_usb_caiaq_input_dispatch ( struct snd_usb_caiaqdev * dev ,
char * buf ,
2007-03-26 19:11:24 +02:00
unsigned int len )
{
2007-11-21 16:45:23 +01:00
if ( ! dev - > input_dev | | len < 1 )
2007-03-26 19:11:24 +02:00
return ;
switch ( buf [ 0 ] ) {
case EP1_CMD_READ_ANALOG :
2007-11-21 16:45:23 +01:00
snd_caiaq_input_read_analog ( dev , buf + 1 , len - 1 ) ;
2007-03-26 19:11:24 +02:00
break ;
case EP1_CMD_READ_ERP :
2007-11-21 16:45:23 +01:00
snd_caiaq_input_read_erp ( dev , buf + 1 , len - 1 ) ;
2007-03-26 19:11:24 +02:00
break ;
case EP1_CMD_READ_IO :
2007-11-21 16:45:23 +01:00
snd_caiaq_input_read_io ( dev , buf + 1 , len - 1 ) ;
2007-03-26 19:11:24 +02:00
break ;
}
}
int snd_usb_caiaq_input_init ( struct snd_usb_caiaqdev * dev )
{
struct usb_device * usb_dev = dev - > chip . dev ;
struct input_dev * input ;
int i , ret ;
input = input_allocate_device ( ) ;
if ( ! input )
return - ENOMEM ;
2007-11-21 16:45:23 +01:00
usb_make_path ( usb_dev , dev - > phys , sizeof ( dev - > phys ) ) ;
strlcat ( dev - > phys , " /input0 " , sizeof ( dev - > phys ) ) ;
2007-03-26 19:11:24 +02:00
input - > name = dev - > product_name ;
2007-11-21 16:45:23 +01:00
input - > phys = dev - > phys ;
usb_to_input_id ( usb_dev , & input - > id ) ;
input - > dev . parent = & usb_dev - > dev ;
2007-03-26 19:11:24 +02:00
switch ( dev - > chip . usb_id ) {
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_RIGKONTROL2 ) :
2007-10-18 23:40:32 -07:00
input - > evbit [ 0 ] = BIT_MASK ( EV_KEY ) | BIT_MASK ( EV_ABS ) ;
input - > absbit [ 0 ] = BIT_MASK ( ABS_X ) | BIT_MASK ( ABS_Y ) |
BIT_MASK ( ABS_Z ) ;
2007-11-21 16:45:23 +01:00
BUILD_BUG_ON ( sizeof ( dev - > keycode ) < sizeof ( keycode_rk2 ) ) ;
memcpy ( dev - > keycode , keycode_rk2 , sizeof ( keycode_rk2 ) ) ;
2007-03-26 19:11:24 +02:00
input - > keycodemax = ARRAY_SIZE ( keycode_rk2 ) ;
input_set_abs_params ( input , ABS_X , 0 , 4096 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_Y , 0 , 4096 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_Z , 0 , 4096 , 0 , 10 ) ;
snd_usb_caiaq_set_auto_msg ( dev , 1 , 10 , 0 ) ;
break ;
2007-09-17 14:45:14 +02:00
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_RIGKONTROL3 ) :
2007-11-22 11:40:04 +01:00
input - > evbit [ 0 ] = BIT_MASK ( EV_KEY ) | BIT_MASK ( EV_ABS ) ;
input - > absbit [ 0 ] = BIT_MASK ( ABS_X ) | BIT_MASK ( ABS_Y ) |
BIT_MASK ( ABS_Z ) ;
2007-11-21 16:45:23 +01:00
BUILD_BUG_ON ( sizeof ( dev - > keycode ) < sizeof ( keycode_rk3 ) ) ;
memcpy ( dev - > keycode , keycode_rk3 , sizeof ( keycode_rk3 ) ) ;
2007-09-17 14:45:14 +02:00
input - > keycodemax = ARRAY_SIZE ( keycode_rk3 ) ;
input_set_abs_params ( input , ABS_X , 0 , 1024 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_Y , 0 , 1024 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_Z , 0 , 1024 , 0 , 10 ) ;
snd_usb_caiaq_set_auto_msg ( dev , 1 , 10 , 0 ) ;
break ;
2007-03-26 19:11:24 +02:00
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_AK1 ) :
2007-10-18 23:40:32 -07:00
input - > evbit [ 0 ] = BIT_MASK ( EV_KEY ) | BIT_MASK ( EV_ABS ) ;
input - > absbit [ 0 ] = BIT_MASK ( ABS_X ) ;
2007-11-21 16:45:23 +01:00
BUILD_BUG_ON ( sizeof ( dev - > keycode ) < sizeof ( keycode_ak1 ) ) ;
memcpy ( dev - > keycode , keycode_ak1 , sizeof ( keycode_ak1 ) ) ;
2007-03-26 19:11:24 +02:00
input - > keycodemax = ARRAY_SIZE ( keycode_ak1 ) ;
input_set_abs_params ( input , ABS_X , 0 , 999 , 0 , 10 ) ;
snd_usb_caiaq_set_auto_msg ( dev , 1 , 0 , 5 ) ;
break ;
2007-11-22 11:40:04 +01:00
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_KORECONTROLLER ) :
2007-11-26 09:00:56 +01:00
case USB_ID ( USB_VID_NATIVEINSTRUMENTS , USB_PID_KORECONTROLLER2 ) :
2007-11-22 11:40:04 +01:00
input - > evbit [ 0 ] = BIT_MASK ( EV_KEY ) | BIT_MASK ( EV_ABS ) ;
input - > absbit [ 0 ] = BIT_MASK ( ABS_HAT0X ) | BIT_MASK ( ABS_HAT0Y ) |
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 ) < sizeof ( keycode_kore ) ) ;
memcpy ( dev - > keycode , keycode_kore , sizeof ( keycode_kore ) ) ;
input - > keycodemax = ARRAY_SIZE ( keycode_kore ) ;
input_set_abs_params ( input , ABS_HAT0X , 0 , 999 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_HAT0Y , 0 , 999 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_HAT1X , 0 , 999 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_HAT1Y , 0 , 999 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_HAT2X , 0 , 999 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_HAT2Y , 0 , 999 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_HAT3X , 0 , 999 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_HAT3Y , 0 , 999 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_X , 0 , 4096 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_Y , 0 , 4096 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_Z , 0 , 4096 , 0 , 10 ) ;
input_set_abs_params ( input , ABS_MISC , 0 , 255 , 0 , 1 ) ;
snd_usb_caiaq_set_auto_msg ( dev , 1 , 10 , 5 ) ;
break ;
2007-03-26 19:11:24 +02:00
default :
/* no input methods supported on this device */
input_free_device ( input ) ;
return 0 ;
}
2007-11-21 16:45:23 +01:00
input - > keycode = dev - > keycode ;
input - > keycodesize = sizeof ( unsigned short ) ;
for ( i = 0 ; i < input - > keycodemax ; i + + )
__set_bit ( dev - > keycode [ i ] , input - > keybit ) ;
2007-03-26 19:11:24 +02:00
ret = input_register_device ( input ) ;
if ( ret < 0 ) {
input_free_device ( input ) ;
return ret ;
}
dev - > input_dev = input ;
return 0 ;
}
void snd_usb_caiaq_input_free ( struct snd_usb_caiaqdev * dev )
{
if ( ! dev | | ! dev - > input_dev )
return ;
input_unregister_device ( dev - > input_dev ) ;
dev - > input_dev = NULL ;
}