/* * ===================================================================================== * * Filename: hanvon-libusb.c * * Description: Libusb GP0504 handler prototype * * Version: 0.1 * Created: 08/17/2020 04:05:14 PM * Revision: none * Compiler: gcc * * Author: surkeh@protonmail.com * * ===================================================================================== */ #include #include #include #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 #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 //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+ */ #define AM_WHEEL_THRESHOLD 4 #define AM_MAX_TILT_X 0x3f #define AM_MAX_TILT_Y 0x7f #define AM_MAX_PRESSURE 0x400 struct hanvon { unsigned char *data; //dma_addr_t data_dma; struct input_dev *dev; struct usb_device *usbdev; struct urb *irq; int old_wheel_pos; char phys[32]; }; 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; } void display_packets(const unsigned char* buf) { for(int i = 0; i < AM_PACKET_LEN; i++) { printf("0x%x, ", buf[i]); } printf("\n"); } void callback(struct libusb_transfer *transfer) { unsigned char *data = transfer -> buffer; display_packets(data); } void callback_gp0504 (struct libusb_transfer *transfer) { // for callback unsigned char *data = transfer -> buffer; struct libevdev_uinput *ud = transfer -> user_data; switch(data[0]) { case 0x01: break; case 0x02: if((data[1] & 0xf0) != 0) { ; // libevdev_uinput_write_event(ud, ABS_X, ) } break; default: display_packets(data); break; } } // determine which callback devices to use and how to initialize libevdev int init_ctrl(struct libusb_device * const d, struct libevdev * evdev, struct libevdev_uinput *uidev) { int is_ok = 0; if (d == NULL) { return is_ok; } struct libusb_device_descriptor desc; libusb_get_device_descriptor(d, &desc); evdev = libevdev_new(); switch(desc.idProduct) { default: // every tablet has these features - allow fall through libevdev_enable_event_type(evdev, EV_ABS); // enable absolute position libevdev_enable_event_type(evdev, EV_KEY); // enable pen button libevdev_enable_event_code(evdev, EV_KEY, BTN_LEFT, NULL); // pen tap libevdev_enable_event_code(evdev, EV_KEY, BTN_RIGHT, NULL); // pen button case PRODUCT_ID_GP0906: break; case PRODUCT_ID_APPIV0906: break; case PRODUCT_ID_GP0504: libevdev_set_name(evdev, "Hanvon Graphicpal GP0504"); break; } int err = libevdev_uinput_create_from_device(evdev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev); if (err == 0) { is_ok = 1; } 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_exit(NULL); return 0; } struct libevdev *evdev = NULL; struct libevdev_uinput *uidev = NULL; init_ctrl(d, evdev, uidev); 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, uidev, // extra data to send in tx 130); // timeout in milliseconds do { status = libusb_submit_transfer(tx); if (status < 0 ) { return status; } libusb_handle_events(NULL); } while (1); libevdev_uinput_destroy(uidev); return 0; } libusb_device *FindHanvon( libusb_context **context); int HandleData( void ); int main() { #define UNREF_DEVICE 1 #define KEEP_DEVICE_REF 0 libusb_device ** devs; int r = libusb_init(NULL); if (r < 0) { return r; } int count = libusb_get_device_list(NULL, &devs); if (count < 0) { libusb_exit(NULL); return count; } int index = find_device(devs, count); if (index < 0) { printf("Device not plugged in\n"); libusb_exit(NULL); 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; }