View difference between Paste ID: zK8jH2A1 and grZPxRDu
SHOW: | | - or go back to the newest paste.
1
//
2
// Simple hack to change dpi on Logitech G400s
3
// G400s only support: 400, 800, 1600, 2000 and 4000 dpi, all other are interpolate by software
4
//
5
// Based on g400_hack from Przemek Aksamit
6
// https://bitbucket.org/extaliones/g400_hack/src
7
//
8
// gcc -lusb-1.0 -o g400s_hack g400s_hack.c
9
//
10
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <string.h>
14
#include <libusb-1.0/libusb.h>
15
16
#define G400S_VENDOR_ID   0x046d
17
#define G400S_PRODUCT_ID  0xc24c
18
19
#define EXIT_SUCCESS       0
20
#define EXIT_ERROR_ARGS    1
21
#define EXIT_ERROR_DEVICE  2
22
#define EXIT_ERROR_KERNEL  3
23
#define EXIT_ERROR_CLAIM   4
24
#define EXIT_ERROR_WRITE   5
25
26
27
libusb_context *ctx = NULL;
28
libusb_device_handle *handle = NULL;
29
30
int detached = 0;
31
int claimed  = 0;
32
33
34
void usage()
35
{
36-
  printf("Usage: ./g400s_hack ( -400 | -800 | -1600 | -2000 | -4000 )\n");
36+
  printf("Usage: ./g400s_hack ( -400 | -800 | -1600 | -2000 | -4000 | -d | -n)\n");
37
  printf("Highly experimental, use with caution.\n");
38
}
39
40
void cleanup()
41
{
42
  if (claimed)
43
    libusb_release_interface(handle, 1);
44
45
  if (detached)
46
    libusb_attach_kernel_driver(handle, 1);
47
48
  libusb_close(handle);
49
  libusb_exit(ctx);
50
}
51
52
int main(int argc, char **argv)
53
{
54
  if (argc != 2 || argv[1][0] != '-') {
55
    usage();
56
    return EXIT_ERROR_ARGS;
57
  }
58
59
  //131 => 400dpi, 132 => 800dpi, 133 => 1600dpi, 134 => 2000dpi, 135 => 4000dpi
60
  uint16_t dpi_idx = 131;
61
  if      (strcmp(&argv[1][1], "400" ) == 0)
62
    dpi_idx += 0;
63
  else if (strcmp(&argv[1][1], "800" ) == 0)
64
    dpi_idx += 1;
65
  else if (strcmp(&argv[1][1], "1600") == 0)
66
    dpi_idx += 2;
67
  else if (strcmp(&argv[1][1], "2000") == 0)
68
    dpi_idx += 3;
69
  else if (strcmp(&argv[1][1], "4000") == 0)
70
    dpi_idx += 4;
71
  else if (strcmp(&argv[1][1], "d") == 0)
72
    dpi_idx = 0;
73
  else if (strcmp(&argv[1][1], "n") == 0)
74
    dpi_idx = 4;
75
  else {
76-
  printf("Set new DPI: %s (index %i)\n", &argv[1][1], dpi_idx);
76+
77
    return EXIT_ERROR_ARGS;
78
  }
79
80
  if (dpi_idx >= 131) {
81
    printf("Set new DPI: %s (index %i)\n", &argv[1][1], dpi_idx);
82
  }
83
  else {
84
    printf("Set Driver/Native mode: %s (index %i)\n", &argv[1][1], dpi_idx);
85
  }
86
87
  libusb_init(&ctx);
88
89
  handle = libusb_open_device_with_vid_pid(ctx, G400S_VENDOR_ID, G400S_PRODUCT_ID);
90
  libusb_set_debug(ctx, 3);
91
92
  if (!handle) {
93
    fprintf(stderr, "Logitech G400s not found! (Do you have usb rights? Try with sudo?)\n");
94
    cleanup();
95
    return EXIT_ERROR_DEVICE;
96
  }
97
98
  if (libusb_kernel_driver_active(handle, 1) == 1) {
99
    if (libusb_detach_kernel_driver(handle, 1) != 0) {
100
      fprintf(stderr, "Can't detach kernel driver.\n");
101
      cleanup();
102
      return EXIT_ERROR_KERNEL;
103
    }
104
105
    detached = 1;
106
  }
107
108
  if (libusb_claim_interface(handle, 1) != 0) {
109
    fprintf(stderr, "Failed to claim interface.\n");
110
    cleanup();
111
    return EXIT_ERROR_CLAIM;
112
  }
113
114
  claimed = 1;
115
  
116
  if (dpi_idx == 0) {
117
    // Set driver mode, then DPI to 400
118
    char data[2];
119
    data[0] = 0x20; data[1] = 0x01;
120
    int result = libusb_control_transfer (handle, 0x21, 9, 0x0320, 1, data, 2, 1000);
121
    if (result != 2) {
122
      fprintf(stderr, "Error writing to USB device (%d).\n", result);
123
      cleanup();
124
      return EXIT_ERROR_WRITE;
125
    }
126
    dpi_idx = 131;
127
  }
128
129
  if (libusb_control_transfer (handle, 0x40, 2, 0x008e, dpi_idx, NULL, 0, 1000) != 0) {
130
    fprintf(stderr, "Error writing to USB device.\n");
131
    cleanup();
132
    return EXIT_ERROR_WRITE;
133
  }
134
135
  cleanup();
136
  printf("Finished.\n");
137
  return EXIT_SUCCESS;
138
}