ckb-next  beta-v0.2.8 at branch testing
ckb-next driver for corsair devices
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
dpi.c
Go to the documentation of this file.
1 #include "dpi.h"
2 #include "usb.h"
3 
4 void cmd_dpi(usbdevice* kb, usbmode* mode, int dummy, const char* stages, const char* values){
5  int disable = 0;
6  ushort x, y;
7  // Try to scan X,Y values
8  if(sscanf(values, "%hu,%hu", &x, &y) != 2){
9  // If that doesn't work, scan single number
10  if(sscanf(values, "%hu", &x) == 1)
11  y = x;
12  else if(!strncmp(values, "off", 3))
13  // If the right side says "off", disable the level(s)
14  disable = 1;
15  else
16  // Otherwise, quit
17  return;
18  }
19  if((x == 0 || y == 0) && !disable)
20  return;
21  // Scan the left side for stage numbers (comma-separated)
22  int left = strlen(stages);
23  int position = 0, field = 0;
24  char stagename[3];
25  while(position < left && sscanf(stages + position, "%2[^,]%n", stagename, &field) == 1){
26  uchar stagenum;
27  if(sscanf(stagename, "%hhu", &stagenum) && stagenum < DPI_COUNT){
28  // Set DPI for this stage
29  if(disable){
30  mode->dpi.enabled &= ~(1 << stagenum);
31  mode->dpi.x[stagenum] = 0;
32  mode->dpi.y[stagenum] = 0;
33  } else {
34  mode->dpi.enabled |= 1 << stagenum;
35  mode->dpi.x[stagenum] = x;
36  mode->dpi.y[stagenum] = y;
37  }
38  }
39  if(stages[position += field] == ',')
40  position++;
41  }
42 }
43 
44 void cmd_dpisel(usbdevice* kb, usbmode* mode, int dummy1, int dummy2, const char* stage){
45  uchar stagenum;
46  if(sscanf(stage, "%hhu", &stagenum) != 1)
47  return;
48  if(stagenum > DPI_COUNT)
49  return;
50  mode->dpi.current = stagenum;
51 }
52 
53 void cmd_lift(usbdevice* kb, usbmode* mode, int dummy1, int dummy2, const char* height){
54  uchar heightnum;
55  if(sscanf(height, "%hhu", &heightnum) != 1)
56  return;
57  if(heightnum > LIFT_MAX || heightnum < LIFT_MIN)
58  return;
59  mode->dpi.lift = heightnum;
60 }
61 
62 void cmd_snap(usbdevice* kb, usbmode* mode, int dummy1, int dummy2, const char* enable){
63  if(!strcmp(enable, "on"))
64  mode->dpi.snap = 1;
65  if(!strcmp(enable, "off"))
66  mode->dpi.snap = 0;
67 }
68 
69 char* printdpi(const dpiset* dpi, const usbdevice* kb){
70  // Print all DPI settings
71  const int BUFFER_LEN = 100;
72  char* buffer = malloc(BUFFER_LEN);
73  int length = 0;
74  for(int i = 0; i < DPI_COUNT; i++){
75  // Print the stage number
76  int newlen = 0;
77  snprintf(buffer + length, BUFFER_LEN - length, length == 0 ? "%d%n" : " %d%n", i, &newlen);
78  length += newlen;
79  // Print the DPI settings
80  if(!(dpi->enabled & (1 << i)))
81  snprintf(buffer + length, BUFFER_LEN - length, ":off%n", &newlen);
82  else
83  snprintf(buffer + length, BUFFER_LEN - length, ":%u,%u%n", dpi->x[i], dpi->y[i], &newlen);
84  length += newlen;
85  }
86  return buffer;
87 }
88 
89 int updatedpi(usbdevice* kb, int force){
90  if(!kb->active)
91  return 0;
92  dpiset* lastdpi = &kb->profile->lastdpi;
93  dpiset* newdpi = &kb->profile->currentmode->dpi;
94  // Don't do anything if the settings haven't changed
95  if(!force && !lastdpi->forceupdate && !newdpi->forceupdate
96  && !memcmp(lastdpi, newdpi, sizeof(dpiset)))
97  return 0;
98  lastdpi->forceupdate = newdpi->forceupdate = 0;
99 
100  // Send X/Y DPIs
101  for(int i = 0; i < DPI_COUNT; i++){
102  uchar data_pkt[MSG_SIZE] = { 0x07, 0x13, 0xd0, 0 };
103  data_pkt[2] |= i;
104  *(ushort*)(data_pkt + 5) = newdpi->x[i];
105  *(ushort*)(data_pkt + 7) = newdpi->y[i];
106  if(!usbsend(kb, data_pkt, 1))
107  return -1;
108  }
109 
110  // Send settings
111  uchar data_pkt[4][MSG_SIZE] = {
112  { 0x07, 0x13, 0x05, 0, newdpi->enabled },
113  { 0x07, 0x13, 0x02, 0, newdpi->current },
114  { 0x07, 0x13, 0x03, 0, newdpi->lift },
115  { 0x07, 0x13, 0x04, 0, newdpi->snap, 0x05 }
116  };
117  if(!usbsend(kb, data_pkt[0], 4))
118  return -2;
119  // Finished
120  memcpy(lastdpi, newdpi, sizeof(dpiset));
121  return 0;
122 }
123 
124 int savedpi(usbdevice* kb, dpiset* dpi, lighting* light){
125  // Send X/Y DPIs
126  for(int i = 0; i < DPI_COUNT; i++){
127  uchar data_pkt[MSG_SIZE] = { 0x07, 0x13, 0xd0, 1 };
128  data_pkt[2] |= i;
129  *(ushort*)(data_pkt + 5) = dpi->x[i];
130  *(ushort*)(data_pkt + 7) = dpi->y[i];
131  // Save the RGB value for this setting too
132  data_pkt[9] = light->r[LED_MOUSE + N_MOUSE_ZONES + i];
133  data_pkt[10] = light->g[LED_MOUSE + N_MOUSE_ZONES + i];
134  data_pkt[11] = light->b[LED_MOUSE + N_MOUSE_ZONES + i];
135  if(!usbsend(kb, data_pkt, 1))
136  return -1;
137  }
138 
139  // Send settings
140  uchar data_pkt[4][MSG_SIZE] = {
141  { 0x07, 0x13, 0x05, 1, dpi->enabled },
142  { 0x07, 0x13, 0x02, 1, dpi->current },
143  { 0x07, 0x13, 0x03, 1, dpi->lift },
144  { 0x07, 0x13, 0x04, 1, dpi->snap, 0x05 }
145  };
146  if(!usbsend(kb, data_pkt[0], 4))
147  return -2;
148  // Finished
149  return 0;
150 }
151 
152 int loaddpi(usbdevice* kb, dpiset* dpi, lighting* light){
153  // Ask for settings
154  uchar data_pkt[4][MSG_SIZE] = {
155  { 0x0e, 0x13, 0x05, 1, },
156  { 0x0e, 0x13, 0x02, 1, },
157  { 0x0e, 0x13, 0x03, 1, },
158  { 0x0e, 0x13, 0x04, 1, }
159  };
160  uchar in_pkt[4][MSG_SIZE];
161  for(int i = 0; i < 4; i++){
162  if(!usbrecv(kb, data_pkt[i], in_pkt[i]))
163  return -2;
164  if(memcmp(in_pkt[i], data_pkt[i], 4)){
165  ckb_err("Bad input header\n");
166  return -3;
167  }
168  }
169  // Copy data from device
170  dpi->enabled = in_pkt[0][4];
171  dpi->enabled &= (1 << DPI_COUNT) - 1;
172  dpi->current = in_pkt[1][4];
173  if(dpi->current >= DPI_COUNT)
174  dpi->current = 0;
175  dpi->lift = in_pkt[2][4];
176  if(dpi->lift < LIFT_MIN || dpi->lift > LIFT_MAX)
177  dpi->lift = LIFT_MIN;
178  dpi->snap = !!in_pkt[3][4];
179 
180  // Get X/Y DPIs
181  for(int i = 0; i < DPI_COUNT; i++){
182  uchar data_pkt[MSG_SIZE] = { 0x0e, 0x13, 0xd0, 1 };
183  uchar in_pkt[MSG_SIZE];
184  data_pkt[2] |= i;
185  if(!usbrecv(kb, data_pkt, in_pkt))
186  return -2;
187  if(memcmp(in_pkt, data_pkt, 4)){
188  ckb_err("Bad input header\n");
189  return -3;
190  }
191  // Copy to profile
192  dpi->x[i] = *(ushort*)(in_pkt + 5);
193  dpi->y[i] = *(ushort*)(in_pkt + 7);
194  light->r[LED_MOUSE + N_MOUSE_ZONES + i] = in_pkt[9];
195  light->g[LED_MOUSE + N_MOUSE_ZONES + i] = in_pkt[10];
196  light->b[LED_MOUSE + N_MOUSE_ZONES + i] = in_pkt[11];
197  }
198  // Finished. Set SW DPI light to the current hardware level
199  light->r[LED_MOUSE + 2] = light->r[LED_MOUSE + N_MOUSE_ZONES + dpi->current];
200  light->g[LED_MOUSE + 2] = light->g[LED_MOUSE + N_MOUSE_ZONES + dpi->current];
201  light->b[LED_MOUSE + 2] = light->b[LED_MOUSE + N_MOUSE_ZONES + dpi->current];
202  return 0;
203 }
#define MSG_SIZE
Definition: structures.h:176
void cmd_dpi(usbdevice *kb, usbmode *mode, int dummy, const char *stages, const char *values)
Definition: dpi.c:4
uchar b[152+11]
Definition: structures.h:76
usbprofile * profile
Definition: structures.h:221
uchar enabled
Definition: structures.h:63
void cmd_lift(usbdevice *kb, usbmode *mode, int dummy1, int dummy2, const char *height)
Definition: dpi.c:53
usbmode * currentmode
Definition: structures.h:105
int savedpi(usbdevice *kb, dpiset *dpi, lighting *light)
Definition: dpi.c:124
#define ckb_err(fmt, args...)
Definition: includes.h:49
char * buffer
Definition: devnode.c:336
#define N_MOUSE_ZONES
Definition: keymap.h:40
char active
Definition: structures.h:231
int updatedpi(usbdevice *kb, int force)
Definition: dpi.c:89
dpiset lastdpi
Definition: structures.h:108
dpiset dpi
Definition: structures.h:86
ushort x[6]
Definition: structures.h:59
unsigned char uchar
Definition: includes.h:24
void cmd_snap(usbdevice *kb, usbmode *mode, int dummy1, int dummy2, const char *enable)
Definition: dpi.c:62
#define LIFT_MIN
Definition: structures.h:55
uchar snap
Definition: structures.h:67
uchar lift
Definition: structures.h:65
unsigned short ushort
Definition: includes.h:25
#define DPI_COUNT
Definition: structures.h:54
#define LIFT_MAX
Definition: structures.h:56
void cmd_dpisel(usbdevice *kb, usbmode *mode, int dummy1, int dummy2, const char *stage)
Definition: dpi.c:44
uchar g[152+11]
Definition: structures.h:75
uchar current
Definition: structures.h:61
#define usbrecv(kb, out_msg, in_msg)
usbrecv macro is used to wrap _usbrecv() with debugging information (file and lineno) ...
Definition: usb.h:256
Definitions for using USB interface.
char * printdpi(const dpiset *dpi, const usbdevice *kb)
Definition: dpi.c:69
uchar r[152+11]
Definition: structures.h:74
ushort y[6]
Definition: structures.h:60
#define usbsend(kb, messages, count)
usbsend macro is used to wrap _usbsend() with debugging information (file and lineno) ...
Definition: usb.h:239
#define LED_MOUSE
Definition: keymap.h:39
uchar forceupdate
Definition: structures.h:69
int loaddpi(usbdevice *kb, dpiset *dpi, lighting *light)
Definition: dpi.c:152