Browse Source

Generalized, default handles GP0504, others MAY work

surkhe 12 months ago
parent
commit
82f283ddb4
  1. 8
      README.md
  2. 176
      hanvon-libusb.c

8
README.md

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
# Hanvon Tablet Drivers
Userspace driver for Hanvon pen tablets adapted from the original Linux kernel driver. Supports tablet features such as pen coordinates, x and y tilts, proximity and pressure detection.
Userspace driver for Hanvon pen tablets adapted from the original Linux kernel driver. Supports tablet features such as pen coordinates, x and y tilt angle, hover detection, pressure detection, and button input.
## Building
make
@ -13,11 +13,11 @@ Run the output executable from a terminal with sudo (preferrably in the backgrou @@ -13,11 +13,11 @@ Run the output executable from a terminal with sudo (preferrably in the backgrou
## Supported Hardware
Currently, only GP0504 is tested and supported.
All tablets supported by the original driver should work with this libusb driver but only the GP0504 has been tested.
The original series of supported hardware:
The original driver supported the following models:
Artmaster I: AM3M, AM0605, AM0806, AM1107, AM1209
ArtMaster: AM3M, AM0605, AM0806, AM1107, AM1209
Rollick: RL0604, RL0504

176
hanvon-libusb.c

@ -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 & 0x1000) / 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 & 0x2000) / 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 & 0x4000) / 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 & 0x8000) / 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 AM1209");
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 NXS1513");
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 APPIV0906");
break;
}

Loading…
Cancel
Save