Guest User

mod_g_hack.c

a guest
Mar 9th, 2011
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.80 KB | None | 0 0
  1. /*
  2.  * mod_g_hack
  3.  * slight modification of Andreas Schneider's g_hack by Bombenbach
  4.  * in order to make it work with logitech G500
  5.  * Big thanks to Andreas Schneider and Marian Kyral
  6.  */
  7.  
  8.  
  9. /*
  10.  * gcc -o g_hack g_hack.c
  11.  * ./g_hack /dev/hidraw0
  12.  *
  13.  * g_hack - proof of conecpt code
  14.  *
  15.  *
  16.  * Copyright (c) 2006-2009 Andreas Schneider <[email protected]>
  17.  * Copyright (c) 2006-2007 Peter Feuerer <[email protected]>
  18.  *
  19.  * License: GPLv2 or later
  20.  *
  21.  * Additional Info:
  22.  *
  23.  * the G-series has two modes:
  24.  *
  25.  * 1. mode: no driver
  26.  * in this mode there is a list of resolutions implemented in the mouse
  27.  * and you can switch between them using the buttons
  28.  *
  29.  * 2. mode is: windows driver
  30.  * in this mode the buttons talk to the driver
  31.  * they have absolute no effect on the hardware in first place
  32.  * the driver gets the button event looks in its table, which resolution to use
  33.  * sends it to the mouse sets the leds and the resolution
  34.  */
  35.  
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <time.h>
  39. #include <string.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <asm/types.h>
  44. #include <fcntl.h>
  45. #include <unistd.h>
  46. #include <linux/hiddev.h>
  47.  
  48. #define VERSION "0.0.7"
  49.  
  50. #define VENDOR 0x046d
  51. #define MOUSE_G5 0xc041
  52. #define MOUSE_G7 0xc51a
  53.  
  54. /* thanks to Michael "sanni" Dewein */
  55. #define MOUSE_G3 0xc042
  56.  
  57. /* thanks to Niels "aboe" Abspoel */
  58. #define MOUSE_G9 0xc048
  59. /* G500's signature*/
  60. #define MOUSE_G500 0xc068
  61.  
  62. /* function borrowed from http://www.lomoco.org/vx_hack.c */
  63. static int query_report(int fd, int id, unsigned int *buf, size_t size) {
  64.   struct hiddev_usage_ref_multi uref;
  65.   struct hiddev_report_info rinfo;
  66.   int i = 0, rc = -1;
  67.  
  68.   rinfo.report_type = HID_REPORT_TYPE_INPUT;
  69.   rinfo.report_id = id;
  70.   rinfo.num_fields = 1;
  71.   rc = ioctl(fd, HIDIOCGREPORT, &rinfo);
  72.   if (rc < 0) {
  73.     perror("HIDIOCGREPORT");
  74.     return rc;
  75.   }
  76.  
  77.   uref.uref.report_type = HID_REPORT_TYPE_INPUT;
  78.   uref.uref.report_id = id;
  79.   uref.uref.field_index = 0;
  80.   uref.uref.usage_index = 0;
  81.   uref.num_values = size;
  82.   rc = ioctl(fd, HIDIOCGUSAGES, &uref);
  83.   if (rc < 0) {
  84.     perror("HIDIOCGUSAGES");
  85.     return rc;
  86.   }
  87.  
  88.   for (i = 0; i < size; i++) {
  89.     buf[i] = uref.values[i];
  90.   }
  91.  
  92.   return rc;
  93. }
  94.  
  95. /*modified send_report since G500 also uses a 20 byte long buffer*/
  96. static int send_report20(int fd, const unsigned char *buf, size_t size) {
  97.   struct hiddev_report_info rinfo;
  98.   struct hiddev_usage_ref uref;
  99.   int i, err;
  100.  
  101.   for (i = 0; i < size; i++) {
  102.     memset(&uref, 0, sizeof(uref));
  103.     uref.report_type = HID_REPORT_TYPE_OUTPUT;
  104.     uref.report_id   = 0x11;
  105.     uref.field_index = 0;
  106.     uref.usage_index = i;
  107.     uref.usage_code  = 0xff000001;
  108.     uref.value       = buf[i];
  109.  
  110.     err = ioctl(fd, HIDIOCSUSAGE, &uref);
  111.     if (err < 0)
  112.       return err;
  113.   }
  114.  
  115.   memset(&rinfo, 0, sizeof(rinfo));
  116.   rinfo.report_type = HID_REPORT_TYPE_OUTPUT;
  117.   rinfo.report_id   = 0x11;
  118.   rinfo.num_fields  = 1;
  119.   err = ioctl(fd, HIDIOCSREPORT, &rinfo);
  120.  
  121.   return err;
  122. }
  123.  
  124. static int send_report(int fd, const unsigned char *buf, size_t size) {
  125.   struct hiddev_report_info rinfo;
  126.   struct hiddev_usage_ref uref;
  127.   int i, err;
  128.  
  129.   for (i = 0; i < size; i++) {
  130.     memset(&uref, 0, sizeof(uref));
  131.     uref.report_type = HID_REPORT_TYPE_OUTPUT;
  132.     uref.report_id   = 0x10;
  133.     uref.field_index = 0;
  134.     uref.usage_index = i;
  135.     uref.usage_code  = 0xff000001;
  136.     uref.value       = buf[i];
  137.  
  138.     err = ioctl(fd, HIDIOCSUSAGE, &uref);
  139.     if (err < 0)
  140.       return err;
  141.   }
  142.  
  143.   memset(&rinfo, 0, sizeof(rinfo));
  144.   rinfo.report_type = HID_REPORT_TYPE_OUTPUT;
  145.   rinfo.report_id   = 0x10;
  146.   rinfo.num_fields  = 1;
  147.   err = ioctl(fd, HIDIOCSREPORT, &rinfo);
  148.  
  149.   return err;
  150. }
  151.  
  152. void send_msg(int fd,char c0,char c1,char c2, char c3, char c4, char c5)
  153. {
  154.   unsigned char b[6];
  155.   b[0]=c0;
  156.   b[1]=c1;
  157.   b[2]=c2;
  158.   b[3]=c3;
  159.   b[4]=c4;
  160.   b[5]=c5;
  161.   if(send_report(fd,b,6)<0)
  162.   {
  163.     perror("error sending to device");
  164.     close(fd);
  165.     exit(1);
  166.   }  
  167. }
  168. /*modified send_msg since G500 also uses a 20 byte long buffer*/
  169. void send_msg20(int fd,char c0,char c1,char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, char c10, char c11, char c12, char c13, char c14 , char c15 , char c16 , char c17, char c18 )
  170. {
  171.   unsigned char b[19];
  172.   b[0]=c0;
  173.   b[1]=c1;
  174.   b[2]=c2;
  175.   b[3]=c3;
  176.   b[4]=c4;
  177.   b[5]=c5;
  178.   b[6]=c6;
  179.   b[7]=c7;
  180.   b[8]=c8;
  181.   b[9]=c9;
  182.   b[10]=c10;
  183.   b[11]=c11;
  184.   b[12]=c12;
  185.   b[13]=c13;
  186.   b[14]=c14;
  187.   b[15]=c15;
  188.   b[16]=c16;
  189.   b[17]=c17;
  190.   b[18]=c18;  
  191.   if(send_report20(fd,b,19)<0)
  192.   {
  193.     perror("error sending to device");
  194.     close(fd);
  195.     exit(1);
  196.   }
  197. }
  198.  
  199.  
  200. int main (int argc, char **argv) {
  201. /*this snippet fo the nanosleep comes from http://timmurphy.org/2009/09/29/nanosleep-in-c-c/ */
  202.  int milisec = 100; // length of time to sleep, in miliseconds
  203.  struct timespec req = {0};
  204.  req.tv_sec = 0;
  205.  req.tv_nsec = milisec * 1000000L;
  206.  
  207.  int dpi_hex1 = 0x00;
  208.  int dpi_hex2 = 0x00;
  209.  int dpi_hex3 = 0x00;
  210.  
  211. /* new function hid_reply to check G500's replies. Contains code from vx_hack.c*/
  212. void hid_reply(int fd) {
  213.   unsigned int buf[6] = {0};
  214.   int i;
  215.   nanosleep(&req, (struct timespec *)NULL);
  216.   if (query_report(fd, 0x10, buf, 6) < 0) {
  217.       perror("query failed");
  218.       close(fd);
  219.       exit(1);
  220.   }
  221.     printf("query result: ");
  222.     for (i = 0; i < 6; i++) {
  223.       printf(" %02x", buf[i]);
  224.   }
  225.     printf("\n");
  226. }
  227.  
  228.   int fd = -1;
  229.   int version;
  230.   int resolution=0;
  231.   struct hiddev_devinfo device_info;
  232.  
  233.   printf("g5hack version: %s\n\n", VERSION);
  234.  
  235.   /* ioctl() requires a file descriptor, so we check we got one, and
  236.      then open it */
  237.   if (argc != 3) {
  238.     fprintf(stderr, "This works only with Logitech G500! Usage: %s hiddevice resolution\n - hiddevice probably /dev/usb/hiddev0 or /dev/hidraw0\n - resolution: 0=400 1=800 2=1600 3=1800 4=2000 5=3200 6=4000 7=5700\n", argv[0]);
  239.     exit(1);
  240.   }
  241.   if ((fd = open(argv[1], O_RDONLY)) < 0) {
  242.     perror("hiddev open");
  243.     exit(1);
  244.   }
  245.   resolution=atoi(argv[2]);
  246.  
  247.   /* ioctl() accesses the underlying driver */
  248.   ioctl(fd, HIDIOCGVERSION, &version);
  249.  
  250.   /* the HIDIOCGVERSION ioctl() returns an int
  251.    * so we unpack it and display it
  252.    * we create a patch
  253.    */
  254.   printf("hiddev driver version is %d.%d.%d\n", version >> 16, (version >> 8) & 0xff, version & 0xff);
  255.  
  256.   /* suck out some device information */
  257.   ioctl(fd, HIDIOCGDEVINFO, &device_info);
  258.  
  259.   /* the HIDIOCGDEVINFO ioctl() returns hiddev_devinfo
  260.    * structure - see <linux/hiddev.h>
  261.    * So we work through the various elements, displaying
  262.    * each of them
  263.    */
  264.   printf("vendor 0x%04hx product 0x%04hx version 0x%04hx ",
  265.       device_info.vendor, device_info.product,
  266.       device_info.version);
  267.   printf("has %i application%s ", device_info.num_applications,
  268.       (device_info.num_applications==1?"":"s"));
  269.   printf("and is on bus: %d   devnum: %d   ifnum: %d\n",
  270.       device_info.busnum, device_info.devnum,
  271.       device_info.ifnum);
  272.  
  273.   /* We have a G500? */
  274.   if((device_info.vendor == (short)VENDOR) && (device_info.product == (short)MOUSE_G500)) {
  275.  
  276.     if(device_info.product == (short)MOUSE_G500)
  277.       printf(">>  G500 Gaming Mouse detected!\n");
  278.  
  279.     if (ioctl(fd, HIDIOCINITREPORT, 0) < 0) {
  280.       perror("hid report init failed");
  281.       exit(1);
  282.     }
  283.       printf("Initializing the mouse\n");
  284.       send_msg(fd,0x00,0x80,0xa1,0x01,0x00,0x02);
  285.       hid_reply(fd);      
  286.       send_msg(fd,0x00,0x83,0xa2,0x01,0x80,0x00);
  287.       hid_reply(fd);      
  288.       send_msg(fd,0x00,0x83,0xa2,0x01,0x88,0x00);
  289.       hid_reply(fd);      
  290.       send_msg(fd,0x00,0x83,0xa2,0x01,0x80,0x00);
  291.       hid_reply(fd);      
  292.       send_msg(fd,0x00,0x83,0xa2,0x01,0x88,0x00);
  293.       hid_reply(fd);      
  294.       send_msg(fd,0x00,0x83,0xa2,0x01,0x80,0x00);
  295.       hid_reply(fd);      
  296.       send_msg(fd,0x00,0x81,0x0f,0x00,0x00,0x00);
  297.       hid_reply(fd);      
  298.       send_msg20(fd,0x00,0x82,0xa0,0x04,0x00,0x01,0x02,0x00,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  299.       hid_reply(fd);            
  300.       send_msg(fd,0x00,0x83,0xa2,0x00,0xa1,0x00);      
  301.       hid_reply(fd);      
  302.       send_msg(fd,0x00,0x83,0xa2,0x00,0xa1,0x00);
  303.       hid_reply(fd);      
  304.       send_msg(fd,0x00,0x83,0x63,0x00,0x00,0x00);
  305.       hid_reply(fd);      
  306.       send_msg(fd,0x00,0x81,0x0f,0x00,0x00,0x00);
  307.       hid_reply(fd);      
  308.       send_msg(fd,0x00,0x80,0x0f,0x00,0x00,0x00);
  309.       hid_reply(fd);      
  310.       send_msg20(fd,0x00,0x90,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x4e,0x00,0x00,0xff,0x00,0x00,0x80,0x00,0x22,0x00);    
  311.       send_msg20(fd,0x00,0x91,0x01,0x22,0x22,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  312.       send_msg20(fd,0x00,0x91,0x02,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x10,0x02);    
  313.       send_msg20(fd,0x00,0x91,0x03,0x81,0x01,0x00,0x81,0x02,0x00,0x81,0x04,0x00,0x81,0x08,0x00,0x81,0x10,0x00,0x81);    
  314.       send_msg20(fd,0x00,0x91,0x04,0x20,0x00,0x81,0x40,0x00,0x81,0x80,0x00,0x81,0x00,0x01,0x81,0x00,0x02,0x8f,0x00);    
  315.       send_msg20(fd,0x00,0x93,0x05,0x00,0x8f,0x00,0x00,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  316.       hid_reply(fd);      
  317.       send_msg(fd,0x00,0x80,0x0f,0x01,0x00,0x00);
  318.       hid_reply(fd);    
  319.      
  320.     switch(resolution){
  321.     case 0:
  322.     //400 DPI
  323.     dpi_hex1 = 0x11;  
  324.     dpi_hex2 = 0xc1;  
  325.     dpi_hex3 = 0x67;  
  326.     break;
  327.    
  328.     case 1:
  329.     //800 DPI
  330.     dpi_hex1 = 0x22;  
  331.     dpi_hex2 = 0x79;  
  332.     dpi_hex3 = 0x13;  
  333.     break;
  334.    
  335.     case 2:
  336.     //1600 DPI
  337.     dpi_hex1 = 0x44;  
  338.     dpi_hex2 = 0x19;  
  339.     dpi_hex3 = 0xda;  
  340.     break;
  341.    
  342.     case 3:
  343.     //1800 DPI
  344.     dpi_hex1 = 0x4d;  
  345.     dpi_hex2 = 0x28;  
  346.     dpi_hex3 = 0x56;  
  347.     break;
  348.    
  349.     case 4:
  350.     //2000 DPI
  351.     dpi_hex1 = 0x55;  
  352.     dpi_hex2 = 0x71;  
  353.     dpi_hex3 = 0xf6;  
  354.     break;
  355.    
  356.     case 5:
  357.     //3200 DPI
  358.     dpi_hex1 = 0x88;
  359.     dpi_hex2 = 0xd8;  
  360.     dpi_hex3 = 0x48;  
  361.     break;
  362.    
  363.     case 6:
  364.     //4000 DPI
  365.     dpi_hex1 = 0xaa;  
  366.     dpi_hex2 = 0x08;  
  367.     dpi_hex3 = 0x10;
  368.     break;
  369.    
  370.     case 7:
  371.     //5700 DPI
  372.     dpi_hex1 = 0xf3;  
  373.     dpi_hex2 = 0xfc;  
  374.     dpi_hex3 = 0x7d;
  375.     break;  
  376.  
  377.  }  
  378.  printf("Changing DPI and allowing DPI buttons to be remapped\n");
  379.     send_msg20(fd,0x00,0x82,0xa0,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00);    
  380.     hid_reply(fd);                                                                                    
  381.     //                                                                                                   V
  382.     send_msg20(fd,0x00,0x90,0x06,0x01,0x02,0x00,0x00,0x00,0x00,0x4e,0x00,0x00,0xff,0x00,0x00,0x80,0x00,dpi_hex1,0x00);        
  383.     //                            V
  384.     send_msg20(fd,0x00,0x91,0x07,dpi_hex1,0x22,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  385.     send_msg20(fd,0x00,0x91,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x10,0x02);
  386.     send_msg20(fd,0x00,0x91,0x09,0x81,0x01,0x00,0x81,0x02,0x00,0x81,0x04,0x00,0x81,0x08,0x00,0x81,0x10,0x00,0x81);    send_msg20(fd,0x00,0x91,0x0a,0x20,0x00,0x83,0x01,0x00,0x83,0x02,0x00,0x81,0x00,0x01,0x81,0x00,0x02,0x8f,0x00);        
  387.     send_msg20(fd,0x00,0x93,0x0b,0x00,0x8f,0x00,0x00,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  388.     hid_reply(fd);
  389.     //                                                                          V    V
  390.     send_msg20(fd,0x00,0x92,0x0c,0x01,0x02,0xff,0x00,0x00,0x00,0x02,0x00,0x00,dpi_hex2,dpi_hex3,0x00,0x00,0x00,0x00,0x00);
  391.     hid_reply(fd);
  392.     send_msg(fd,0x00,0x83,0x63,0x00,0x00,0x00);
  393.     hid_reply(fd);
  394.     send_msg(fd,0x00,0x80,0x0f,0x00,0x00,0x00);
  395.     hid_reply(fd);
  396.     //                                                                                                  V
  397.     send_msg20(fd,0x00,0x90,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x4e,0x00,0x00,0xff,0x00,0x00,0x80,0x00,dpi_hex1,0x00);
  398.     hid_reply(fd);
  399.     //                              V
  400.     send_msg20(fd,0x00,0x91,0x0e,dpi_hex1,0x22,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  401.     hid_reply(fd);
  402.     send_msg20(fd,0x00,0x91,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x10,0x02);        
  403.     send_msg20(fd,0x00,0x91,0x10,0x81,0x01,0x00,0x81,0x02,0x00,0x81,0x04,0x00,0x81,0x08,0x00,0x81,0x10,0x00,0x81);        
  404.     send_msg20(fd,0x00,0x91,0x11,0x20,0x00,0x81,0x40,0x00,0x81,0x80,0x00,0x81,0x00,0x01,0x81,0x00,0x02,0x8f,0x00);        
  405.     send_msg20(fd,0x00,0x93,0x12,0x00,0x8f,0x00,0x00,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  406.     hid_reply(fd);
  407.     send_msg(fd,0x00,0x80,0x0f,0x01,0x00,0x00);
  408.     hid_reply(fd);
  409.     printf ("Done\n");
  410.   }
  411.  
  412.   close(fd);
  413.  
  414.   exit(0);
  415. }
Add Comment
Please, Sign In to add comment