/* * gcc -o lx5fix lx5fix.c * * Based on (only payload changed) * * g5_hiddev - first working hack! * by * Andreas "gladiac" Schneider * Peter "piie" Feuerer * */ #include #include #include #include #include #include #include #include #include #include #define VERSION "0.0.1" static int send_report(int fd, int id, const unsigned int *buf, size_t size) { struct hiddev_report_info rinfo; struct hiddev_usage_ref uref; int i, err; for (i = 0; i < size; i++) { memset(&uref, 0, sizeof(uref)); uref.report_type = HID_REPORT_TYPE_OUTPUT; uref.report_id = id; uref.field_index = 0; uref.usage_index = i; uref.usage_code = 0xff000001; uref.value = buf[i]; err = ioctl(fd, HIDIOCSUSAGE, &uref); if (err < 0) return err; } memset(&rinfo, 0, sizeof(rinfo)); rinfo.report_type = HID_REPORT_TYPE_OUTPUT; rinfo.report_id = id; rinfo.num_fields = 1; err = ioctl(fd, HIDIOCSREPORT, &rinfo); return err; } static int query_report(int fd, int id, unsigned int *buf, size_t size) { struct hiddev_usage_ref_multi uref; struct hiddev_report_info rinfo; int i = 0, rc = -1; rinfo.report_type = HID_REPORT_TYPE_INPUT; rinfo.report_id = id; rinfo.num_fields = 1; rc = ioctl(fd, HIDIOCGREPORT, &rinfo); if (rc < 0) { perror("HIDIOCGREPORT"); return rc; } uref.uref.report_type = HID_REPORT_TYPE_INPUT; uref.uref.report_id = id; uref.uref.field_index = 0; uref.uref.usage_index = 0; uref.num_values = size; rc = ioctl(fd, HIDIOCGUSAGES, &uref); if (rc < 0) { perror("HIDIOCGUSAGES"); return rc; } for (i = 0; i < size; i++) { buf[i] = uref.values[i]; } return rc; } void send_msg(int fd, int id, int c0, int c1, int c2, int c3, int c4, int c5) { int rc = -1; unsigned int b[6]; b[0] = c0; b[1] = c1; b[2] = c2; b[3] = c3; b[4] = c4; b[5] = c5; rc = send_report(fd, id, b, 6); if (rc < 0) { perror("error sending to device"); close(fd); exit(1); } } static int ctr = 0; void send_msg_(int fd, int id, int c0, int c1, int c2, int c3, int c4, int c5) { unsigned int buf[7] = {0}; send_msg(fd, id, c0, c1, c2, c3, c4, c5); if (query_report(fd, 0x10, buf, 6) < 0) { perror("query failed"); close(fd); exit(1); } } int main (int argc, char **argv) { int fd = -1; int i = 0; int version = 0; struct hiddev_devinfo device_info; unsigned int buf[7] = {0}; char *devicenode; /* ioctl() requires a file descriptor, so we check we got one, and then open it */ if (argc == 1) { devicenode = "/dev/usb/hiddev0"; } else if (argc == 2) { devicenode = argv[1]; } else { fprintf(stderr, "Usage: %s hiddevice\n - hiddevice probably /dev/usb/hiddev0\n", argv[0]); exit(1); } if ((fd = open(devicenode, O_RDONLY)) < 0) { perror("hiddev open"); exit(1); } /* ioctl() accesses the underlying driver */ ioctl(fd, HIDIOCGVERSION, &version); /* the HIDIOCGVERSION ioctl() returns an int * so we unpack it and display it * we create a patch */ /* * Initialise the internal report structures */ if (ioctl(fd, HIDIOCINITREPORT, 0) < 0) { perror("hid report init failed"); exit(1); } /* The magic message that disables the ugly scroll-lock-left-right mappings and lets buttons report std button presses * some kind of reset perhaps 0x01, 0x00, 0x00, 0x00 * * Seems to be same command to disable the default dpi +/- button on the logitech 400! * so this shit automatically works with my new mouse too... wiiihiii */ send_msg_(fd, 0x10, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00); // Chorded mouse uses 0x00 instead of 0x01 ? // send_msg_(fd, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00); close(fd); exit(0); }