/* * gcc -o g5_hiddev g5_hiddev.c * * g5_hiddev - first working hack! * * by * Andreas "gladiac" Schneider * Peter "piie" Feuerer * * Additional Info: * * the g-series has two modes: * * 1. mode: no driver * in this mode there is a list of resolutions implemented in the mouse * and you can switch between them using the buttons * * 2. mode is: windows driver * in this mode the buttons talk to the driver * they have absolute no effect on the hardware in first place * the driver gets the button event looks in its table, which resolution to use * sends it to the mouse sets the leds and the resolution */ #include #include #include #include #include #include #include #include #include #include #define VERSION "0.0.7" #define VENDOR 0x046d #define MOUSE_G5 0xc049 #define MOUSE_G7 0xc51a /* thanks to Michael "sanni" Dewein */ #define MOUSE_G3 0xc042 /* thanks to Niels "aboe" Abspoel */ #define MOUSE_G9 0xc048 static int send_report(int fd, const unsigned char *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 = 0x10; 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 = 0x10; rinfo.num_fields = 1; err = ioctl(fd, HIDIOCSREPORT, &rinfo); return err; } void send_msg(int fd,char c0,char c1,char c2, char c3, char c4, char c5) { unsigned char b[6]; b[0]=c0; b[1]=c1; b[2]=c2; b[3]=c3; b[4]=c4; b[5]=c5; if(send_report(fd,b,6)<0) { perror("error sending to device"); close(fd); exit(1); } } int main (int argc, char **argv) { int fd = -1; int version; int resolution=0; struct hiddev_devinfo device_info; printf("g5hack version: %s\n\n", VERSION); /* ioctl() requires a file descriptor, so we check we got one, and then open it */ if (argc != 3) { fprintf(stderr, "Usage: %s hiddevice resolution\n - hiddevice probably /dev/usb/hiddev0\n - resolution: 0=400 1=800 2=1600 3=2000\n only g9: 4-7 (7=3200)\n\n", argv[0]); exit(1); } if ((fd = open(argv[1], O_RDONLY)) < 0) { perror("hiddev open"); exit(1); } resolution=atoi(argv[2]); /* 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 */ printf("hiddev driver version is %d.%d.%d\n", version >> 16, (version >> 8) & 0xff, version & 0xff); /* suck out some device information */ ioctl(fd, HIDIOCGDEVINFO, &device_info); /* the HIDIOCGDEVINFO ioctl() returns hiddev_devinfo * structure - see * So we work through the various elements, displaying * each of them */ printf("vendor 0x%04hx product 0x%04hx version 0x%04hx ", device_info.vendor, device_info.product, device_info.version); printf("has %i application%s ", device_info.num_applications, (device_info.num_applications==1?"":"s")); printf("and is on bus: %d devnum: %d ifnum: %d\n", device_info.busnum, device_info.devnum, device_info.ifnum); /* We have a G5? */ if((device_info.vendor == (short)VENDOR) && ((device_info.product == (short)MOUSE_G3) || (device_info.product == (short)MOUSE_G9) || (device_info.product == (short)MOUSE_G5) || (device_info.product == (short)MOUSE_G7))) { if(device_info.product == (short)MOUSE_G3) printf(">> G3 Gaming Mouse detected!\n"); if(device_info.product == (short)MOUSE_G9) printf(">> G9 Gaming Mouse detected!\n"); if(device_info.product == (short)MOUSE_G5) printf(">> G5 Gaming Mouse detected!\n"); if(device_info.product == (short)MOUSE_G7) printf(">> G7 cordless Gaming Mouse detected!\n"); /* * Initialise the internal report structures * * The G5 has an additional HID Interface * with a report descriptor. */ if (ioctl(fd, HIDIOCINITREPORT, 0) < 0) { perror("hid report init failed"); exit(1); } /* disable speed buttons */ send_msg(fd,0x00, 0x80, 0x01, 0x00, 0x00, 0x00); /* the g5 has only 4 resolutions: 400, 800, 1600, * 2000. the rest of the resolutions available in the * windows driver are interpolated by software. * fucking shit -> logitech is cheating!! */ switch(resolution){ case 0: /* set current speed to 400dpi */ send_msg(fd,0x00, 0x80, 0x63, 0x80, 0x00, 0x00); /* turn off all speed leds */ send_msg(fd,0x00, 0x80, 0x51, 0x11, 0x01, 0x00); break; case 1: /* set current speed to 800dpi */ send_msg(fd,0x00, 0x80, 0x63, 0x81, 0x00, 0x00); /* turn on first led */ send_msg(fd,0x00, 0x80, 0x51, 0x12, 0x01, 0x00); break; case 2: /* set current speed to 1600dpi */ send_msg(fd,0x00, 0x80, 0x63, 0x82, 0x00, 0x00); /* turn on second led */ send_msg(fd,0x00, 0x80, 0x51, 0x21, 0x01, 0x00); break; case 3: /* set current speed to 2000dpi */ send_msg(fd,0x00, 0x80, 0x63, 0x83, 0x00, 0x00); /* turn on third led */ send_msg(fd,0x00, 0x80, 0x51, 0x11, 0x02, 0x00); break; case 4: /* set current speed to whatever dpi * - only available for g9 */ if(device_info.product == (short)MOUSE_G9){ send_msg(fd,0x00, 0x80, 0x63, 0x84, 0x00, 0x00); /* turn on third led */ send_msg(fd,0x00, 0x80, 0x51, 0x11, 0x02, 0x00); } else{ printf("speed not supported for your device\n"); } break; case 5: /* set current speed to whatever dpi * - only available for g9 */ if(device_info.product == (short)MOUSE_G9){ send_msg(fd,0x00, 0x80, 0x63, 0x85, 0x00, 0x00); /* turn on third led */ send_msg(fd,0x00, 0x80, 0x51, 0x11, 0x02, 0x00); } else{ printf("speed not supported for your device\n"); } break; case 6: /* set current speed to whatever dpi (most probably 3200) * - only available for g9 */ if(device_info.product == (short)MOUSE_G9){ send_msg(fd,0x00, 0x80, 0x63, 0x86, 0x00, 0x00); /* turn on third led */ send_msg(fd,0x00, 0x80, 0x51, 0x11, 0x02, 0x00); } else{ printf("speed not supported for your device\n"); } break; case 7: /* set current speed to whatever dpi (most probably 3200) * - only available for g9 */ if(device_info.product == (short)MOUSE_G9){ send_msg(fd,0x00, 0x80, 0x63, 0x87, 0x00, 0x00); /* turn on third led */ send_msg(fd,0x00, 0x80, 0x51, 0x11, 0x02, 0x00); } else{ printf("speed not supported for your device\n"); } break; default: printf("speed not supported for your device\n"); break; } /* foobar: */ /* at lowest speed ("-" button does not function anymore) */ /* send_msg(fd,0x00, 0x81, 0x51, 0x00, 0x00, 0x00); */ /* turn off all speed leds */ /* send_msg(fd,0x00, 0x80, 0x51, 0x11, 0x01, 0x00); */ /* turn on all speed leds */ /* send_msg(fd,0x00, 0x80, 0x51, 0x22, 0x02, 0x00); */ } /* G5 */ close(fd); exit(0); }