Guest User

rever_g_hack.c

a guest
Mar 9th, 2011
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.39 KB | None | 0 0
  1. /*
  2.  * rever_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 <mail@cynapses.org>
  17.  * Copyright (c) 2006-2007 Peter Feuerer <piie@piie.net>
  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.  
  208. /* new function hid_reply to check G500's replies. Contains code from vx_hack.c*/
  209. void hid_reply(int fd) {
  210.   unsigned int buf[6] = {0};
  211.   int i;
  212.   nanosleep(&req, (struct timespec *)NULL);
  213.   if (query_report(fd, 0x10, buf, 6) < 0) {
  214.       perror("query failed");
  215.       close(fd);
  216.       exit(1);
  217.   }
  218.     printf("query result: ");
  219.     for (i = 0; i < 6; i++) {
  220.       printf(" %02x", buf[i]);
  221.   }
  222.     printf("\n");
  223. }
  224.  
  225.   int fd = -1;
  226.   int version;
  227.   struct hiddev_devinfo device_info;
  228.  
  229.   printf("g5hack version: %s\n\n", VERSION);
  230.  
  231.   /* ioctl() requires a file descriptor, so we check we got one, and
  232.      then open it */
  233.   if (argc != 2) {
  234.     fprintf(stderr, "This works only with Logitech G500! Usage: %s hiddevice \n - hiddevice probably /dev/usb/hiddev0 or /dev/hidraw0\n", argv[0]);
  235.     exit(1);
  236.   }
  237.   if ((fd = open(argv[1], O_RDONLY)) < 0) {
  238.     perror("hiddev open");
  239.     exit(1);
  240.   }
  241.  
  242.   /* ioctl() accesses the underlying driver */
  243.   ioctl(fd, HIDIOCGVERSION, &version);
  244.  
  245.   /* the HIDIOCGVERSION ioctl() returns an int
  246.    * so we unpack it and display it
  247.    * we create a patch
  248.    */
  249.   printf("hiddev driver version is %d.%d.%d\n", version >> 16, (version >> 8) & 0xff, version & 0xff);
  250.  
  251.   /* suck out some device information */
  252.   ioctl(fd, HIDIOCGDEVINFO, &device_info);
  253.  
  254.   /* the HIDIOCGDEVINFO ioctl() returns hiddev_devinfo
  255.    * structure - see <linux/hiddev.h>
  256.    * So we work through the various elements, displaying
  257.    * each of them
  258.    */
  259.   printf("vendor 0x%04hx product 0x%04hx version 0x%04hx ",
  260.       device_info.vendor, device_info.product,
  261.       device_info.version);
  262.   printf("has %i application%s ", device_info.num_applications,
  263.       (device_info.num_applications==1?"":"s"));
  264.   printf("and is on bus: %d   devnum: %d   ifnum: %d\n",
  265.       device_info.busnum, device_info.devnum,
  266.       device_info.ifnum);
  267.  
  268.   /* We have a G500? */
  269.   if((device_info.vendor == (short)VENDOR) && (device_info.product == (short)MOUSE_G500)) {
  270.  
  271.     if(device_info.product == (short)MOUSE_G500)
  272.       printf(">>  G500 Gaming Mouse detected!\n");
  273.  
  274.     if (ioctl(fd, HIDIOCINITREPORT, 0) < 0) {
  275.       perror("hid report init failed");
  276.       exit(1);
  277.     }
  278.       printf("Initializing the mouse\n");
  279.       send_msg(fd,0x00,0x80,0xa1,0x01,0x00,0x02);
  280.       hid_reply(fd);      
  281.       send_msg(fd,0x00,0x83,0xa2,0x01,0x80,0x00);
  282.       hid_reply(fd);      
  283.       send_msg(fd,0x00,0x83,0xa2,0x01,0x88,0x00);
  284.       hid_reply(fd);      
  285.       send_msg(fd,0x00,0x83,0xa2,0x01,0x80,0x00);
  286.       hid_reply(fd);      
  287.       send_msg(fd,0x00,0x83,0xa2,0x01,0x88,0x00);
  288.       hid_reply(fd);      
  289.       send_msg(fd,0x00,0x83,0xa2,0x01,0x80,0x00);
  290.       hid_reply(fd);      
  291.       send_msg(fd,0x00,0x81,0x0f,0x00,0x00,0x00);
  292.       hid_reply(fd);      
  293.       send_msg20(fd,0x00,0x82,0xa0,0x04,0x00,0x01,0x02,0x00,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  294.       hid_reply(fd);            
  295.       send_msg(fd,0x00,0x83,0xa2,0x00,0xa1,0x00);      
  296.       hid_reply(fd);      
  297.       send_msg(fd,0x00,0x83,0xa2,0x00,0xa1,0x00);
  298.       hid_reply(fd);      
  299.       send_msg(fd,0x00,0x83,0x63,0x00,0x00,0x00);
  300.       hid_reply(fd);      
  301.       send_msg(fd,0x00,0x81,0x0f,0x00,0x00,0x00);
  302.       hid_reply(fd);      
  303.       send_msg(fd,0x00,0x80,0x0f,0x00,0x00,0x00);
  304.       hid_reply(fd);      
  305.       send_msg20(fd,0x00,0x90,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x4e,0x00,0x00,0xff,0x00,0x00,0x80,0x00,0x22,0x00);    
  306.       send_msg20(fd,0x00,0x91,0x01,0x22,0x22,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  307.       send_msg20(fd,0x00,0x91,0x02,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x10,0x02);    
  308.       send_msg20(fd,0x00,0x91,0x03,0x81,0x01,0x00,0x81,0x02,0x00,0x81,0x04,0x00,0x81,0x08,0x00,0x81,0x10,0x00,0x81);    
  309.       send_msg20(fd,0x00,0x91,0x04,0x20,0x00,0x81,0x40,0x00,0x81,0x80,0x00,0x81,0x00,0x01,0x81,0x00,0x02,0x8f,0x00);    
  310.       send_msg20(fd,0x00,0x93,0x05,0x00,0x8f,0x00,0x00,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  311.       hid_reply(fd);      
  312.       send_msg(fd,0x00,0x80,0x0f,0x01,0x00,0x00);
  313.       hid_reply(fd);    
  314.        
  315.    
  316.  printf("Activating DPI Buttons with the standard values 400, 800 and 2000 DPI\n");
  317.     send_msg20(fd,0x00,0x82,0xa0,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00);    
  318.     hid_reply(fd);                                                                                    
  319.     //                                                                                                   V
  320.     send_msg20(fd,0x00,0x90,0x06,0x01,0x02,0x00,0x00,0x00,0x00,0x4e,0x00,0x00,0xff,0x00,0x00,0x80,0x00,0x11,0x00);        
  321.     //                            V
  322.     send_msg20(fd,0x00,0x91,0x07,0x11,0x22,0x11,0x00,0x22,0x00,0x22,0x22,0x12,0x00,0x55,0x00,0x55,0x22,0x22,0x00);    
  323.     send_msg20(fd,0x00,0x91,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x10,0x10,0x02);
  324.     send_msg20(fd,0x00,0x91,0x09,0x81,0x01,0x00,0x81,0x02,0x00,0x81,0x04,0x00,0x81,0x08,0x00,0x81,0x10,0x00,0x81);    
  325.     send_msg20(fd,0x00,0x91,0x0a,0x20,0x00,0x83,0x01,0x00,0x83,0x02,0x00,0x83,0x04,0x00,0x83,0x08,0x00,0x8f,0x00);        
  326.     send_msg20(fd,0x00,0x93,0x0b,0x00,0x8f,0x00,0x00,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  327.     hid_reply(fd);
  328.     //                                                                          V    V
  329.     send_msg20(fd,0x00,0x92,0x0c,0x01,0x02,0xff,0x00,0x00,0x00,0x02,0x00,0x00,0xdb,0x5e,0x00,0x00,0x00,0x00,0x00);
  330.     hid_reply(fd);
  331.     send_msg(fd,0x00,0x83,0x63,0x00,0x00,0x00);
  332.     hid_reply(fd);
  333.     //                                                                                                  V
  334.     send_msg20(fd,0x00,0x90,0x0d,0x01,0x00,0xa1,0x00,0x00,0x00,0x4e,0x00,0x00,0xff,0x00,0x00,0x80,0x00,0x11,0x00);
  335.     hid_reply(fd);
  336.     //                              
  337.     send_msg20(fd,0x00,0x91,0x0e,0x11,0x22,0x11,0x00,0x22,0x00,0x22,0x22,0x12,0x00,0x55,0x00,0x55,0x22,0x22,0x00);    
  338.     hid_reply(fd);
  339.     send_msg20(fd,0x00,0x91,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x10,0x10,0x02);        
  340.     send_msg20(fd,0x00,0x91,0x10,0x81,0x01,0x00,0x81,0x02,0x00,0x81,0x04,0x00,0x81,0x08,0x00,0x81,0x10,0x00,0x81);        
  341.     send_msg20(fd,0x00,0x91,0x11,0x20,0x00,0x81,0x40,0x00,0x81,0x80,0x00,0x83,0x04,0x00,0x83,0x08,0x00,0x8f,0x00);        
  342.     send_msg20(fd,0x00,0x93,0x12,0x00,0x8f,0x00,0x00,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  343.     hid_reply(fd);
  344.     send_msg(fd,0x00,0x80,0x0f,0x01,0x00,0xa1);
  345.     hid_reply(fd);
  346.     send_msg20(fd,0x00,0x90,0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x4e,0x00,0x00,0xff,0x00,0x00,0x80,0x00,0x11,0x00);  
  347.     send_msg20(fd,0x00,0x91,0x14,0x11,0x22,0x11,0x00,0x22,0x00,0x22,0x22,0x12,0x00,0x55,0x00,0x55,0x22,0x22,0x00);    
  348.     send_msg20(fd,0x00,0x91,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x10,0x02);
  349.     send_msg20(fd,0x00,0x91,0x16,0x81,0x01,0x00,0x81,0x02,0x00,0x81,0x04,0x00,0x81,0x08,0x00,0x81,0x10,0x00,0x81);    
  350.     send_msg20(fd,0x00,0x91,0x17,0x20,0x00,0x81,0x40,0x00,0x81,0x80,0x00,0x83,0x04,0x00,0x83,0x08,0x00,0x8f,0x00);        
  351.     send_msg20(fd,0x00,0x93,0x18,0x00,0x8f,0x00,0x00,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);    
  352.     hid_reply(fd);
  353.     send_msg(fd,0x00,0x80,0x0f,0x01,0x00,0x00);
  354.     hid_reply(fd);
  355.    
  356.    
  357.     printf ("Done\n");
  358.    
  359.  
  360.  
  361.   }
  362.  
  363.   close(fd);
  364.  
  365.   exit(0);
  366. }
Add Comment
Please, Sign In to add comment