Skip to content

Instantly share code, notes, and snippets.

@userid
Created September 20, 2017 10:51
Show Gist options
  • Select an option

  • Save userid/4fd001fb93a2c73adcba3be9e6e90578 to your computer and use it in GitHub Desktop.

Select an option

Save userid/4fd001fb93a2c73adcba3be9e6e90578 to your computer and use it in GitHub Desktop.
https://wiki.archlinux.org/index.php/Mouse_buttons
Binding + and - in Logitech G5 mouse
If you want to bind the buttons + and - in G5/7 mouse, which normally changes DPI, you have to use g5hack [2] released by a lomoco author.
wget http://piie.net/temp/g5_hiddev.c
gcc -o g5hack g5_hiddev.c
./g5hack /dev/usb/hiddev0 3
This will change your DPI to 2000, light the 1st LED and disables DPI on-the-fly changing, so you can use it with evrouter. If you would use it frequently I suggest you to copy it to the /usr/bin directory:
# cp g5hack /usr/bin/
If you want to bind your + and - buttons you must copy the line at the bottom (one with the comment '"-" button does not function anymore' above) to the mode you will be using, like, for example, under the "case 3:" you can put it on the line with the comment 'turn on third led' above (deleting the old one before of course).
For the newest G5 mouse which is reported as "product 0xc049" original hack does not work. You have to simply change the #define MOUSE_G5 0xc041 to #define MOUSE_G5 0xc049 and recompile.
You can execute the g5hack tool at system start up using systemd unit. See Systemd#Writing unit files for detail.
/*
* gcc -o g5_hiddev g5_hiddev.c
*
* g5_hiddev - first working hack!
*
* by
* Andreas "gladiac" Schneider <andreas.schneider@linuX-gamers.net>
* Peter "piie" Feuerer <peter.feuerer@linuX-gamers.net>
*
* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <asm/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/hiddev.h>
#define VERSION "0.0.7"
#define VENDOR 0x046d
#define MOUSE_G5 0xc041
#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 <linux/hiddev.h>
* 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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment