@ -24,53 +24,61 @@
@@ -24,53 +24,61 @@
# include <libevdev/libevdev.h>
# include <libevdev/libevdev-uinput.h>
// #include <asm/unaligned.h>
# define STATE_SUCCESS 0
# define STATE_NOT_FOUND 1
# define VENDOR_ID_HANVON 0x0b57
# define PRODUCT_ID_AM3M 0x8528
# define PRODUCT_ID_AM0806 0x8502
# define PRODUCT_ID_AM0605 0x8503
# define PRODUCT_ID_AM1107 0x8505
# define PRODUCT_ID_AM1209 0x8501
# define PRODUCT_ID_RL0604 0x851f
# define PRODUCT_ID_RL0504 0x851d
# define PRODUCT_ID_GP0806 0x8039
# define PRODUCT_ID_GP0806B 0x8511
# define PRODUCT_ID_GP0605 0x8512
# define PRODUCT_ID_GP0605A 0x803a
# define PRODUCT_ID_GP0504 0x8037
# define PRODUCT_ID_NXS1513 0x8030
# define PRODUCT_ID_GP0906 0x8521
# define PRODUCT_ID_APPIV0906 0x8532
# define AM_PACKET_LEN 10
# define AM_WHEEL_THRESHOLD 4
# define AM_MAX_ABS_X 0x27DE
# define AM_MAX_ABS_Y 0x1CFE
# define AM_MAX_TILT_X 0x3F
# define AM_MAX_TILT_Y 0x7F
# define AM_MAX_PRESSURE 0x400
# define APPIV_MAX_ABS_X 0x5750
# define APPIV_MAX_ABS_Y 0x5750
# define STATE_SUCCESS 0
# define STATE_NOT_FOUND 1
# define VENDOR_ID_HANVON 0x0b57
# define PRODUCT_ID_AM3M 0x8528
# define PRODUCT_ID_AM0806 0x8502
# define PRODUCT_ID_AM0605 0x8503
# define PRODUCT_ID_AM1107 0x8505
# define PRODUCT_ID_AM1209 0x8501
# define PRODUCT_ID_RL0604 0x851f
# define PRODUCT_ID_RL0504 0x851d
# define PRODUCT_ID_GP0806 0x8039
# define PRODUCT_ID_GP0806B 0x8511
# define PRODUCT_ID_GP0605 0x8512
# define PRODUCT_ID_GP0605A 0x803a
# define PRODUCT_ID_GP0504 0x8037
# define PRODUCT_ID_NXS1513 0x8030
# define PRODUCT_ID_GP0906 0x8521
# define PRODUCT_ID_APPIV0906 0x8532
# define AM_PACKET_LEN 10
# define AM_RESOLUTION 40
# define AM_WHEEL_THRESHOLD 4
# define AM_MAX_ABS_X 0x27DE
# define AM_MAX_ABS_Y 0x1CFE
# define AM_MAX_TILT_X 0x3F
# define AM_MAX_TILT_Y 0x7F
# define AM_MAX_PRESSURE 0x400
# define APPIV_MAX_ABS_X 0x5750
# define APPIV_MAX_ABS_Y 0x5750
# define BUTTON_EVENT_GP 0x01
# define PEN_EVENT 0x02
# define BUTTON_EVENT_0906 0x0C
static int lbuttons [ ] = { BTN_0 , BTN_1 , BTN_2 , BTN_3 } ; /* reported on all AMs */
static int rbuttons [ ] = { BTN_4 , BTN_5 , BTN_6 , BTN_7 } ; /* reported on AM1107+ */
struct hanvon_message {
unsigned char msgtype ;
unsigned char is_move ;
unsigned char x_movement ;
unsigned char extra_buttons ;
unsigned char y_movement ;
unsigned char unused ;
unsigned short x_movement ;
unsigned short y_movement ;
unsigned char pressure ;
unsigned char x_tilt ;
unsigned char y_tilt ;
} ;
// GLOBAL
int wheel_position ;
int find_device ( libusb_device * * list , unsigned int count ) {
if ( count < 0 ) {
return - 1 ;
@ -117,6 +125,31 @@ void callback(struct libusb_transfer *transfer) {
@@ -117,6 +125,31 @@ void callback(struct libusb_transfer *transfer) {
display_packets ( data ) ;
}
static inline void report_buttons ( struct libevdev_uinput * ud ,
int buttons [ ] ,
unsigned char data )
{
int err = 0 ;
if ( ( data & 0xf0 ) = = 0xa0 ) {
// TODO test that these are the correct buttons and all buttons are covered
err = libevdev_uinput_write_event ( ud , EV_KEY , buttons [ 1 ] , ( data & 0x02 ) ) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event ( ud , EV_KEY , buttons [ 2 ] , ( data & 0x04 ) ) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event ( ud , EV_KEY , buttons [ 3 ] , ( data & 0x08 ) ) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
} else if ( data < = 0x3f ) { /* slider area active */
int delta = data - wheel_position ;
if ( abs ( delta ) < AM_WHEEL_THRESHOLD ) {
err = libevdev_uinput_write_event ( ud , EV_REL , REL_WHEEL , delta ) ; // TODO test delta as input
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
wheel_position = data ;
}
}
}
// NOTE:
// Judging by the original driver, this should work for all but may not work
// for the APPIV0906. Possibly needs little endian for APPIV0906 x and y data
@ -130,10 +163,16 @@ void callback_default (struct libusb_transfer *tx) { // for callback
@@ -130,10 +163,16 @@ void callback_default (struct libusb_transfer *tx) { // for callback
int err = 0 ;
struct libevdev_uinput * ud = tx - > user_data ;
switch ( msg - > msgtype ) {
case 0x01 :
display_packets ( data ) ;
case BUTTON_EVENT_GP :
if ( data [ 1 ] = = 0x55 ) { // left side buttons
report_buttons ( ud , lbuttons , msg - > x_movement ) ; // button pressed data in same place as position data
}
if ( data [ 3 ] = = 0xAA ) { // right side buttons (am1107, am1209
report_buttons ( ud , rbuttons , msg - > y_movement ) ; // button pressed data in same place as position data
}
break ;
case 0x02 :
case PEN_EVENT :
/* is_move values:
0x80 : near , 0x02 : button press
0x10 : floating , 0x01 : touching */
@ -157,7 +196,7 @@ void callback_default (struct libusb_transfer *tx) { // for callback
@@ -157,7 +196,7 @@ void callback_default (struct libusb_transfer *tx) { // for callback
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
}
err = libevdev_uinput_write_event (
ud , EV_ABS , ABS_PRESSURE , msg - > pressure
ud , EV_ABS , ABS_PRESSURE , msg - > pressure * 8 // reference original driver
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event (
@ -176,48 +215,51 @@ void callback_default (struct libusb_transfer *tx) { // for callback
@@ -176,48 +215,51 @@ void callback_default (struct libusb_transfer *tx) { // for callback
ud , EV_KEY , BTN_RIGHT , ( msg - > is_move & 0x02 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
// data[1]:
// 0x10 = lift, 0x90 = close, 0x91 = press
// 0x12 = btn (lift), 0x92 = btn (close), 0x93 = btn (press)
break ;
case BUTTON_EVENT_0906 :
// TODO confirm this is the byte that contains button flags
err = libevdev_uinput_write_event (
ud , EV_KEY , BTN_0 , ( msg - > extra_buttons & 0x01 ) / 2
ud , EV_KEY , BTN_0 , ( msg - > is_move & 0x0100 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event (
ud , EV_KEY , BTN_1 , ( msg - > extra_buttons & 0x02 ) / 2
ud , EV_KEY , BTN_1 , ( msg - > is_move & 0x0200 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event (
ud , EV_KEY , BTN_2 , ( msg - > extra_buttons & 0x04 ) / 2
ud , EV_KEY , BTN_2 , ( msg - > is_move & 0x0400 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event (
ud , EV_KEY , BTN_3 , ( msg - > extra_buttons & 0x08 ) / 2
ud , EV_KEY , BTN_3 , ( msg - > is_move & 0x0800 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event (
ud , EV_KEY , BTN_4 , ( msg - > extra_buttons & 0x10 ) / 2
ud , EV_KEY , BTN_4 , ( msg - > is_move & 0x100 0 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event (
ud , EV_KEY , BTN_5 , ( msg - > extra_buttons & 0x20 ) / 2
ud , EV_KEY , BTN_5 , ( msg - > is_move & 0x200 0 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event (
ud , EV_KEY , BTN_6 , ( msg - > extra_buttons & 0x40 ) / 2
ud , EV_KEY , BTN_6 , ( msg - > is_move & 0x400 0 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
err = libevdev_uinput_write_event (
ud , EV_KEY , BTN_7 , ( msg - > extra_buttons & 0x80 ) / 2
ud , EV_KEY , BTN_7 , ( msg - > is_move & 0x800 0 ) / 2
) ;
if ( err ) { DEBUG ( " err: %d \n " , err ) ; }
// data[1]:
// 0x10 = lift, 0x90 = close, 0x91 = press
// 0x12 = btn (lift), 0x92 = btn (close), 0x93 = btn (press)
display_packets ( data ) ;
break ;
default :
display_packets ( data ) ;
// do nothing
break ;
}
// always display packets
display_packets ( data ) ;
err + = libevdev_uinput_write_event ( ud , EV_SYN , SYN_REPORT , 0 ) ;
if ( err ! = 0 ) {
printf ( " error : gp0504, %i \n " , err ) ;
@ -231,6 +273,7 @@ int init_ctrl(struct libusb_device * const d,
@@ -231,6 +273,7 @@ int init_ctrl(struct libusb_device * const d,
struct libevdev_uinput * * uidev ) {
struct input_absinfo * abs ;
printf ( " init_ctrl: %x \n " , uidev ) ;
wheel_position = AM_WHEEL_THRESHOLD - 1 ; // init global
if ( d = = NULL ) {
return - 1 ;
}
@ -263,7 +306,7 @@ int init_ctrl(struct libusb_device * const d,
@@ -263,7 +306,7 @@ int init_ctrl(struct libusb_device * const d,
}
abs - > fuzz = 0 ;
abs - > flat = 0 ;
abs - > resolution = 40 ;
abs - > resolution = AM_RESOLUTION ;
if ( libevdev_enable_event_code ( ( * evdev ) , EV_ABS , ABS_X , abs ) < 0 ) {
DEBUG ( " %s " , " failed to register absolute x \n " ) ;
is_ok = - 1 ;
@ -279,7 +322,7 @@ int init_ctrl(struct libusb_device * const d,
@@ -279,7 +322,7 @@ int init_ctrl(struct libusb_device * const d,
abs - > maximum = AM_MAX_ABS_Y ;
break ;
}
abs - > resolution = 40 ;
abs - > resolution = AM_RESOLUTION ;
if ( libevdev_enable_event_code ( ( * evdev ) , EV_ABS , ABS_Y , abs ) < 0 ) {
DEBUG ( " %s " , " failed to register absolute y \n " ) ;
is_ok = - 1 ;
@ -312,6 +355,12 @@ int init_ctrl(struct libusb_device * const d,
@@ -312,6 +355,12 @@ int init_ctrl(struct libusb_device * const d,
is_ok = - 1 ;
}
// Scroll wheel is NOT universal
if ( libevdev_enable_event_code ( ( * evdev ) , EV_REL , REL_WHEEL , NULL ) < 0 ) {
DEBUG ( " %s " , " failed to register scroll wheel \n " ) ;
is_ok = - 1 ;
}
// set up device-specific inputs
switch ( desc . idProduct ) {
case PRODUCT_ID_AM3M :
@ -333,6 +382,9 @@ int init_ctrl(struct libusb_device * const d,
@@ -333,6 +382,9 @@ int init_ctrl(struct libusb_device * const d,
libevdev_enable_event_code ( ( * evdev ) , EV_KEY , BTN_6 , NULL ) ;
libevdev_enable_event_code ( ( * evdev ) , EV_KEY , BTN_7 , NULL ) ;
break ;
default :
// do nothing
break ;
}
// set up libevdev device name strings
@ -353,7 +405,7 @@ int init_ctrl(struct libusb_device * const d,
@@ -353,7 +405,7 @@ int init_ctrl(struct libusb_device * const d,
libevdev_set_name ( ( * evdev ) , " Hanvon Art Master AM1107 " ) ;
break ;
case PRODUCT_ID_AM1209 :
libevdev_set_name ( ( * evdev ) , " Hanvon AM1209 " ) ;
libevdev_set_name ( ( * evdev ) , " Hanvon ArtMaster A M1209 " ) ;
break ;
case PRODUCT_ID_RL0604 :
libevdev_set_name ( ( * evdev ) , " Hanvon Rollick 0604 " ) ;
@ -377,13 +429,13 @@ int init_ctrl(struct libusb_device * const d,
@@ -377,13 +429,13 @@ int init_ctrl(struct libusb_device * const d,
libevdev_set_name ( ( * evdev ) , " Hanvon Graphicpal 0504 " ) ;
break ;
case PRODUCT_ID_NXS1513 :
libevdev_set_name ( ( * evdev ) , " Hanvon NXS1513 " ) ;
libevdev_set_name ( ( * evdev ) , " Hanvon Nilox N XS1513 " ) ;
break ;
case PRODUCT_ID_GP0906 :
libevdev_set_name ( ( * evdev ) , " Hanvon Graphicpal 0906 " ) ;
break ;
case PRODUCT_ID_APPIV0906 :
libevdev_set_name ( ( * evdev ) , " Hanvon APPIV0906 " ) ;
libevdev_set_name ( ( * evdev ) , " Hanvon Art Painter Pro A PPIV0906 " ) ;
break ;
}