diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index d8b6bbe..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "hidapi"] - path = hidapi - url = https://github.com/libusb/hidapi diff --git a/Makefile b/Makefile index 5083e09..584da41 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ obj-m += hanvon.o all: - gcc hanvon-libusb.c -I/usr/include/libevdev-1.0/ -L/usr/local/lib -lusb-1.0 -ludev -levdev -g + gcc hanvon-libusb.c -I/usr/include/libevdev-1.0/ -L/usr/local/lib -lusb-1.0 -ludev -levdev -g -o hvlusb archive: tar f - --exclude=.git -C ../ -c hanvon | gzip -c9 > ../hanvon-`date +%Y%m%d`.tgz diff --git a/README b/README deleted file mode 100644 index 67d5577..0000000 --- a/README +++ /dev/null @@ -1,40 +0,0 @@ -Hanvon tablet driver -==================== - -Driver for Linux kernels which supports complete functionality of the tablet: -pen coordinates, touch/float/click detection, pressure, x and y tilt, pen -button. On Artmaster I four simple tablet buttons (note that the first -one works only together with pen activity), and the slider button. - - -Supported hardware -================== - -AM3M, AM0605, AM0806, AM1107, AM1209 -RL0604, RL0504 -GP0504, GP0605, GP0605+, GP0806, GP0906 -NXS1315 -APPIV0906 - -AM - Artmaster I, RL - Rollick, GP - GraphicPal, NXS - Nilox -APP - Art Painter Pro - - -Installation -============ - -Type 'make' to compile the module. New file hanvon.ko will be produced in -current directory. Load the module with root permissions - -insmod ./hanvon.ko - -If everything goes right the tablet should start working immediately. - - -Diagnostics -=========== - -After insmod, check with dmesg, if the module was loaded properly. -"USB Hanvon tablet driver" should appear in the listing. - -lsmod should also contain hanvon in its listing: lsmod | grep hanvon diff --git a/README.md b/README.md new file mode 100644 index 0000000..d39527f --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ + +# 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. + +## Building + make + +## Usage + sudo hvlusb + +Run the output executable from a terminal with sudo (preferrably in the background). + +## Supported Hardware + +Currently, only GP0504 is tested and supported. + +The original series of supported hardware: + +Artmaster I: AM3M, AM0605, AM0806, AM1107, AM1209 + +Rollick: RL0604, RL0504 + +GraphicPal: GP0504, GP0605, GP0605+, GP0806, GP0906 + +Nilox: NXS1315 + +Art Painter Pro: APPIV0906 +__________________ + +upstream repository: https://git.teknik.io/scuti/hanvon-linux + +forked from: https://github.com/ondrah/hanvon diff --git a/hanvon-libusb.c b/hanvon-libusb.c index 493e4a2..58b1dc2 100644 --- a/hanvon-libusb.c +++ b/hanvon-libusb.c @@ -1,20 +1,20 @@ /* - * ===================================================================================== - * - * Filename: hanvon-libusb.c - * - * Description: libusb Hanvon tablet driver - * - * Version: 0.1 - * Created: 08/17/2020 04:05:14 PM - * Revision: none - * Compiler: gcc - * - * Maintaned by: scuti@teknik.io - * surkeh@protonmail.com - * - * ===================================================================================== - */ +* ===================================================================================== +* +* Filename: hanvon-libusb.c +* +* Description: libusb Hanvon tablet driver +* +* Version: 0.1 +* Created: 08/17/2020 04:05:14 PM +* Revision: none +* Compiler: gcc +* +* Maintained by: scuti@teknik.io +* surkeh@protonmail.com +* +* ===================================================================================== +*/ #define DEBUG(msg,...) fprintf(stderr,"%s(%d): " msg , __FILE__,__LINE__,__VA_ARGS__) @@ -24,15 +24,11 @@ #include #include - // #include #define STATE_SUCCESS 0 #define STATE_NOT_FOUND 1 -#define UNREF_DEVICE 1 -#define KEEP_DEVICE_REF 0 - #define VENDOR_ID_HANVON 0x0b57 #define PRODUCT_ID_AM3M 0x8528 #define PRODUCT_ID_AM0806 0x8502 @@ -61,8 +57,7 @@ #define AM_MAX_TILT_Y 0x7f #define AM_MAX_PRESSURE 0x400 -struct hanvon_message -{ +struct hanvon_message { unsigned char msgtype; unsigned char is_move; unsigned short x_movement; @@ -73,40 +68,37 @@ struct hanvon_message }; int find_device(libusb_device **list, unsigned int count) { - if (count < 0) { - return -1; - } - int found = -1; - struct libusb_device_descriptor desc; - for (unsigned int i = 0; i < count; i++) { - libusb_device *t = list[i]; - libusb_get_device_descriptor(list[i], &desc); - -// printf( "Dev%u ID %04x:%04x\n", (i), desc.idVendor, desc.idProduct ); - - if (desc.idVendor == VENDOR_ID_HANVON) { - switch(desc.idProduct) { - default: - break; - case PRODUCT_ID_AM0806: - case PRODUCT_ID_AM0605: - case PRODUCT_ID_AM1107: - case PRODUCT_ID_AM1209: - case PRODUCT_ID_RL0604: - case PRODUCT_ID_RL0504: - case PRODUCT_ID_GP0806: - case PRODUCT_ID_GP0806B: - case PRODUCT_ID_GP0605: - case PRODUCT_ID_GP0605A: - case PRODUCT_ID_GP0504: - case PRODUCT_ID_NXS1513: - case PRODUCT_ID_GP0906: - case PRODUCT_ID_APPIV0906: - return i; - } // end switch - } // end if - } // end for - return found; + if (count < 0) { + return -1; + } + int found = -1; + struct libusb_device_descriptor desc; + for (unsigned int i = 0; i < count; i++) { + libusb_device *t = list[i]; + libusb_get_device_descriptor(list[i], &desc); + if (desc.idVendor == VENDOR_ID_HANVON) { + switch(desc.idProduct) { + default: + break; + case PRODUCT_ID_AM0806: + case PRODUCT_ID_AM0605: + case PRODUCT_ID_AM1107: + case PRODUCT_ID_AM1209: + case PRODUCT_ID_RL0604: + case PRODUCT_ID_RL0504: + case PRODUCT_ID_GP0806: + case PRODUCT_ID_GP0806B: + case PRODUCT_ID_GP0605: + case PRODUCT_ID_GP0605A: + case PRODUCT_ID_GP0504: + case PRODUCT_ID_NXS1513: + case PRODUCT_ID_GP0906: + case PRODUCT_ID_APPIV0906: + return i; + } // end switch + } // end if + } // end for + return found; } void display_packets(const unsigned char* buf) { @@ -124,51 +116,59 @@ void callback(struct libusb_transfer *transfer) { void callback_gp0504 (struct libusb_transfer *tx) { // for callback unsigned char *data = tx -> buffer; struct hanvon_message *msg = (struct hanvon_message *)tx -> buffer; - unsigned short temp; - int err = 0; + int err = 0; struct libevdev_uinput *ud = tx -> user_data; switch(msg->msgtype) { case 0x01: display_packets(data); break; case 0x02: - /*is_move values: - 0x80: near - 0x10: floating - 0x02: button press - 0x01: touching - */ - err = libevdev_uinput_write_event(ud, EV_KEY, BTN_TOOL_PEN, msg->is_move & (0x80|0x10)); + /* is_move values: + 0x80: near, 0x02: button press + 0x10: floating, 0x01: touching */ + err = libevdev_uinput_write_event( + ud, EV_KEY, BTN_TOOL_PEN, msg->is_move & (0x80|0x10) + ); if(err) { DEBUG("err: %d\n",err); } if(msg->is_move & (0x80|0x10)) { msg->x_movement = htobe16(msg->x_movement); //DEBUG("Set X to %x\n",msg->x_movement); - err = libevdev_uinput_write_event(ud, EV_ABS, ABS_X, msg->x_movement); + err = libevdev_uinput_write_event( + ud, EV_ABS, ABS_X, msg->x_movement + ); if(err) { DEBUG("err: %d\n",err); } msg->y_movement = htobe16(msg->y_movement); //DEBUG("Set Y to %x\n",msg->y_movement); - err = libevdev_uinput_write_event(ud, EV_ABS, ABS_Y, msg->y_movement); + err = libevdev_uinput_write_event( + ud, EV_ABS, ABS_Y, msg->y_movement + ); if(err) { DEBUG("err: %d\n",err); } } - - err = libevdev_uinput_write_event(ud, EV_ABS, ABS_PRESSURE, msg->pressure); + err = libevdev_uinput_write_event( + ud, EV_ABS, ABS_PRESSURE, msg->pressure + ); if(err) { DEBUG("err: %d\n",err); } - err = libevdev_uinput_write_event(ud, EV_ABS, ABS_TILT_X, msg->y_tilt); + err = libevdev_uinput_write_event( + ud, EV_ABS, ABS_TILT_X, msg->x_tilt + ); if(err) { DEBUG("err: %d\n",err); } - err = libevdev_uinput_write_event(ud, EV_ABS, ABS_TILT_Y, msg->x_tilt); + err = libevdev_uinput_write_event( + ud, EV_ABS, ABS_TILT_Y, msg->y_tilt + ); if(err) { DEBUG("err: %d\n",err); } - err = libevdev_uinput_write_event(ud, EV_KEY, BTN_LEFT, msg->is_move & 0x01); + err = libevdev_uinput_write_event( + ud, EV_KEY, BTN_LEFT, msg->is_move & 0x01 + ); if(err) { DEBUG("err: %d\n",err); } - err = libevdev_uinput_write_event(ud, EV_KEY, BTN_RIGHT, (msg->is_move & 0x02) / 2); + err = libevdev_uinput_write_event( + 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) - { - display_packets(data); - } + display_packets(data); break; default: display_packets(data); @@ -183,13 +183,15 @@ void callback_gp0504 (struct libusb_transfer *tx) { // for callback } // https://www.freedesktop.org/software/libevdev/doc/latest/group__kernel.html -int init_ctrl(struct libusb_device * const d, struct libevdev **evdev, struct libevdev_uinput **uidev) { +int init_ctrl(struct libusb_device * const d, + struct libevdev **evdev, + struct libevdev_uinput **uidev) { struct input_absinfo *abs; printf("init_ctrl: %x\n", uidev); - int is_ok = 0; if (d == NULL) { - return is_ok; + return -1; } + int is_ok = 0; struct libusb_device_descriptor desc; libusb_get_device_descriptor(d, &desc); (*evdev) = libevdev_new(); @@ -201,8 +203,8 @@ int init_ctrl(struct libusb_device * const d, struct libevdev **evdev, struct li libevdev_enable_event_code((*evdev), EV_KEY, BTN_TOOL_PEN, NULL); libevdev_enable_event_code((*evdev), EV_KEY, BTN_LEFT, NULL); // pen tap libevdev_enable_event_code((*evdev), EV_KEY, BTN_RIGHT, NULL); // pen button - libevdev_enable_event_type((*evdev), EV_ABS); // enable absolute position, pressure, tilt - + // enable absolute position, pressure, tilt + libevdev_enable_event_type((*evdev), EV_ABS); abs = malloc(sizeof(struct input_absinfo)); // set up absolute x coordinate input abs->value = 0x1000; @@ -213,24 +215,25 @@ int init_ctrl(struct libusb_device * const d, struct libevdev **evdev, struct li abs->resolution = 40; if(libevdev_enable_event_code((*evdev), EV_ABS, ABS_X, abs)<0) { DEBUG("%s","failed to register absolute x\n"); + is_ok = -1; } // set up absolute y coordinate input abs->value = 0x1000; abs->minimum = 0; abs->maximum = 0x1cfe; - abs->fuzz = 0; - abs->flat = 0; abs->resolution = 40; if(libevdev_enable_event_code((*evdev), EV_ABS, ABS_Y, abs)<0) { DEBUG("%s","failed to register absolute y\n"); + is_ok = -1; } // set up pressure input abs -> value = 0; abs -> minimum = 0; - abs -> maximum = 0xff; + abs -> maximum = AM_MAX_PRESSURE; abs -> resolution = 0; if(libevdev_enable_event_code((*evdev), EV_ABS, ABS_PRESSURE, abs)<0) { - DEBUG("%s","failed to register pressure\n"); + DEBUG("%s","failed to register pressure\n"); + is_ok = -1; } // set up tilt x input abs -> value = 0; @@ -238,7 +241,8 @@ int init_ctrl(struct libusb_device * const d, struct libevdev **evdev, struct li abs -> maximum = AM_MAX_TILT_X; abs -> resolution = 0; if(libevdev_enable_event_code((*evdev), EV_ABS, ABS_TILT_X, abs)<0) { - DEBUG("%s","failed to register x tilt\n"); + DEBUG("%s","failed to register x tilt\n"); + is_ok = -1; } // set up tilt y input abs -> value = 0; @@ -246,9 +250,9 @@ int init_ctrl(struct libusb_device * const d, struct libevdev **evdev, struct li abs -> maximum = AM_MAX_TILT_Y; abs -> resolution = 0; if(libevdev_enable_event_code((*evdev), EV_ABS, ABS_TILT_Y, abs)<0) { - DEBUG("%s","failed to register y tilt\n"); + DEBUG("%s","failed to register y tilt\n"); + is_ok = -1; } - switch(desc.idProduct) { case PRODUCT_ID_GP0504: libevdev_set_name((*evdev), "Hanvon Graphicpal GP0504"); @@ -258,61 +262,59 @@ int init_ctrl(struct libusb_device * const d, struct libevdev **evdev, struct li case PRODUCT_ID_APPIV0906: break; } - int err = libevdev_uinput_create_from_device((*evdev), LIBEVDEV_UINPUT_OPEN_MANAGED, uidev); + int err = libevdev_uinput_create_from_device( + (*evdev), LIBEVDEV_UINPUT_OPEN_MANAGED, uidev + ); printf("Initializing controls status: %x, \n", uidev); free(abs); return is_ok; } int handle_device_lusb(libusb_device *d) { - libusb_device_handle *h; - int status = libusb_open(d, &h); - if (status < 0 || h == NULL) { - printf("Error opening device, %i.\n", status); + libusb_device_handle *h; + int status = libusb_open(d, &h); + if (status < 0 || h == NULL) { + printf("Error opening device, %i.\n", status); return 0; - } + } struct libevdev *evdev = NULL; struct libevdev_uinput *uidev = NULL; printf("handle_device: %x\n", uidev); - init_ctrl(d, &evdev, &uidev); + if (init_ctrl(d, &evdev, &uidev) < 0) { + return 0; + } if (evdev == NULL || uidev == NULL) { printf("Error initializing controls, %x, %x.\n", evdev, uidev); return 0; } - - struct libusb_transfer *tx; - const int ENDPOINT_ADDR = 0x81; // bEndpointAddress from lsusb -v -// AM_PACKET_LEN = 10; // wMaxPacketSize from lsusb -v - unsigned char buffer[AM_PACKET_LEN]; + struct libusb_transfer *tx; + const int ENDPOINT_ADDR = 0x81; // bEndpointAddress from lsusb -v + //AM_PACKET_LEN = 10; // wMaxPacketSize from lsusb -v + unsigned char buffer[AM_PACKET_LEN]; // Allocate memory for transfer, configure, then submit tx = libusb_alloc_transfer(0); - libusb_fill_interrupt_transfer( tx, - h, - ENDPOINT_ADDR, - buffer, - AM_PACKET_LEN, - callback_gp0504, - uidev, // extra data to send in tx - 130); // timeout in milliseconds + libusb_fill_interrupt_transfer( tx, + h, + ENDPOINT_ADDR, + buffer, + AM_PACKET_LEN, + callback_gp0504, + uidev, // extra data to send in tx + 130); // timeout in milliseconds do { - status = libusb_submit_transfer(tx); - if (status < 0 ) { - //return status; - //continue; - } - libusb_handle_events(NULL); + status = libusb_submit_transfer(tx); + if (status < 0 ) { + printf("warning: usb transfer status = %i\n", status); + //continue; + } + libusb_handle_events(NULL); } while (1); libevdev_uinput_destroy(uidev); return 0; } -libusb_device *FindHanvon( libusb_context **context); -int HandleData( void ); - - -int main() -{ +int main() { #define UNREF_DEVICE 1 #define KEEP_DEVICE_REF 0 @@ -326,60 +328,15 @@ int main() libusb_exit(NULL); return count; } - int index = find_device(devs, count); - if (index < 0) { - printf("Device not plugged in\n"); + int index = find_device(devs, count); + if (index < 0) { + printf("Device not plugged in\n"); libusb_exit(NULL); - return 0; - } + return 0; + } libusb_device *device = devs[index]; libusb_free_device_list (devs, UNREF_DEVICE); int s = handle_device_lusb(device); libusb_exit(NULL); return 0; } - - - -libusb_device *FindHanvon( libusb_context **context) -{ - libusb_device **deviceList; - libusb_device *found = NULL; - ssize_t nDevices = libusb_get_device_list( context[0], &deviceList); - if( nDevices > 0 ) - { - struct libusb_device_descriptor description; - - for( ssize_t i = 0; i < nDevices; i++ ) - { - libusb_device *device = deviceList[i]; - libusb_get_device_descriptor(device, &description); - //printf( "Dev%u ID %04x:%04x\n", (i + 1), description.idVendor, description.idProduct ); - if( description.idVendor == VENDOR_ID_HANVON ) - { - switch( description.idProduct ) - case PRODUCT_ID_AM0806: - case PRODUCT_ID_AM0605: - case PRODUCT_ID_AM1107: - case PRODUCT_ID_AM1209: - case PRODUCT_ID_RL0604: - case PRODUCT_ID_RL0504: - case PRODUCT_ID_GP0806: - case PRODUCT_ID_GP0806B: - case PRODUCT_ID_GP0605: - case PRODUCT_ID_GP0605A: - case PRODUCT_ID_GP0504: - case PRODUCT_ID_NXS1513: - case PRODUCT_ID_GP0906: - case PRODUCT_ID_APPIV0906: - found = device; - break; - } - } - printf( "\n\n" ); - } - - libusb_free_device_list( deviceList, UNREF_DEVICE ); - return found; -} - diff --git a/hidapi b/hidapi deleted file mode 160000 index cdc473d..0000000 --- a/hidapi +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cdc473dfe43f6432dda7ad53d7656b8ae8ff968b