ckb-next  v0.2.8 at branch master
ckb-next driver for corsair devices
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
profile.c
Go to the documentation of this file.
1 #include "command.h"
2 #include "device.h"
3 #include "input.h"
4 #include "led.h"
5 #include "profile.h"
6 
7 // Percent-enconding conversions
8 void urldecode2(char* dst, const char* src){
9  char a, b;
10  char s;
11  while((s = *src)){
12  if((s == '%') &&
13  ((a = src[1]) && (b = src[2])) &&
14  (isxdigit(a) && isxdigit(b))){
15  if(a >= 'a')
16  a -= 'a'-'A';
17  if(a >= 'A')
18  a -= 'A' - 10;
19  else
20  a -= '0';
21  if(b >= 'a')
22  b -= 'a'-'A';
23  if(b >= 'A')
24  b -= 'A' - 10;
25  else
26  b -= '0';
27  *dst++ = 16 * a + b;
28  src += 3;
29  } else {
30  *dst++ = s;
31  src++;
32  }
33  }
34  *dst = '\0';
35 }
36 
37 void urlencode2(char* dst, const char* src){
38  char s;
39  while((s = *src++)){
40  if(s <= ',' || s == '/' ||
41  (s >= ':' && s <= '@') ||
42  s == '[' || s == ']' ||
43  s >= 0x7F){
44  char a = s >> 4, b = s & 0xF;
45  if(a >= 10)
46  a += 'A' - 10;
47  else
48  a += '0';
49  if(b >= 10)
50  b += 'A' - 10;
51  else
52  b += '0';
53  dst[0] = '%';
54  dst[1] = a;
55  dst[2] = b;
56  dst += 3;
57  } else
58  *dst++ = s;
59  }
60  *dst = '\0';
61 }
62 
63 // GUID conversions
64 int setid(usbid* id, const char* guid){
65  int32_t data1;
66  int16_t data2, data3, data4a;
67  char data4b[6];
68  if(sscanf(guid, "{%08X-%04hX-%04hX-%04hX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
69  &data1, &data2, &data3, &data4a, data4b, data4b + 1, data4b + 2, data4b + 3, data4b + 4, data4b + 5) != 10)
70  return 0;
71  memcpy(id->guid + 0x0, &data1, 4);
72  memcpy(id->guid + 0x4, &data2, 2);
73  memcpy(id->guid + 0x6, &data3, 2);
74  memcpy(id->guid + 0x8, &data4a, 2);
75  memcpy(id->guid + 0xA, data4b, 6);
76  return 1;
77 }
78 
79 char* getid(usbid* id){
80  int32_t data1;
81  int16_t data2, data3, data4a;
82  char data4b[6];
83  memcpy(&data1, id->guid + 0x0, 4);
84  memcpy(&data2, id->guid + 0x4, 2);
85  memcpy(&data3, id->guid + 0x6, 2);
86  memcpy(&data4a, id->guid + 0x8, 2);
87  memcpy(data4b, id->guid + 0xA, 6);
88  char* guid = malloc(39);
89  snprintf(guid, 39, "{%08X-%04hX-%04hX-%04hX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
90  data1, data2, data3, data4a, data4b[0], data4b[1], data4b[2], data4b[3], data4b[4], data4b[5]);
91  return guid;
92 }
93 
94 // UTF-8/UTF-16 conversions (srclen and dstlen in characters - 1 byte UTF8, 2 bytes UTF16)
95 static iconv_t utf8to16 = 0, utf16to8 = 0;
96 
97 void u16enc(char* in, ushort* out, size_t* srclen, size_t* dstlen){
98  if(!utf8to16)
99  utf8to16 = iconv_open("UTF-16LE", "UTF-8");
100  memset(out, 0, *dstlen * 2);
101  *dstlen = *dstlen * 2 - 2;
102  iconv(utf8to16, &in, srclen, (char**)&out, dstlen);
103 }
104 
105 void u16dec(ushort* in, char* out, size_t* srclen, size_t* dstlen){
106  if(!utf16to8)
107  utf16to8 = iconv_open("UTF-8", "UTF-16LE");
108  size_t srclen2 = 0, srclenmax = *srclen;
109  for(; srclen2 < srclenmax; srclen2++){
110  if(!in[srclen2])
111  break;
112  }
113  *srclen = srclen2 * 2;
114  iconv(utf16to8, (char**)&in, srclen, &out, dstlen);
115 }
116 
117 void cmd_name(usbdevice* kb, usbmode* mode, int dummy1, int dummy2, const char* name){
118  (void)kb;
119  (void)dummy1;
120  (void)dummy2;
121 
122  char decoded[strlen(name) + 1];
123  urldecode2(decoded, name);
124  size_t srclen = strlen(decoded), dstlen = MD_NAME_LEN;
125  u16enc(decoded, mode->name, &srclen, &dstlen);
126 }
127 
128 void cmd_profilename(usbdevice* kb, usbmode* dummy1, int dummy2, int dummy3, const char* name){
129  (void)dummy1;
130  (void)dummy2;
131  (void)dummy3;
132 
133  usbprofile* profile = kb->profile;
134  char decoded[strlen(name) + 1];
135  urldecode2(decoded, name);
136  size_t srclen = strlen(decoded), dstlen = PR_NAME_LEN;
137  u16enc(decoded, profile->name, &srclen, &dstlen);
138 }
139 
140 char* printname(ushort* name, int length){
141  // Convert the name to UTF-8
142  char* buffer = calloc(1, length * 4 - 3);
143  size_t srclen = length, dstlen = length * 4 - 4;
144  u16dec(name, buffer, &srclen, &dstlen);
145  // URL-encode it
146  char* buffer2 = malloc(strlen(buffer) * 3 + 1);
147  urlencode2(buffer2, buffer);
148  free(buffer);
149  return buffer2;
150 }
151 
152 char* getmodename(usbmode* mode){
153  return printname(mode->name, MD_NAME_LEN);
154 }
155 
156 char* getprofilename(usbprofile* profile){
157  return printname(profile->name, PR_NAME_LEN);
158 }
159 
160 char* gethwmodename(hwprofile* profile, int index){
161  return printname(profile->name[index + 1], MD_NAME_LEN);
162 }
163 
164 char* gethwprofilename(hwprofile* profile){
165  return printname(profile->name[0], MD_NAME_LEN);
166 }
167 
168 void cmd_id(usbdevice* kb, usbmode* mode, int dummy1, int dummy2, const char* id){
169  (void)kb;
170  (void)dummy1;
171  (void)dummy2;
172 
173  // ID is either a GUID or an 8-digit hex number
174  int newmodified;
175  if(!setid(&mode->id, id) && sscanf(id, "%08x", &newmodified) == 1)
176  memcpy(mode->id.modified, &newmodified, sizeof(newmodified));
177 }
178 
179 void cmd_profileid(usbdevice* kb, usbmode* mode, int dummy1, int dummy2, const char* id){
180  (void)mode;
181  (void)dummy1;
182  (void)dummy2;
183 
184  usbprofile* profile = kb->profile;
185  int newmodified;
186  if(!setid(&profile->id, id) && sscanf(id, "%08x", &newmodified) == 1)
187  memcpy(profile->id.modified, &newmodified, sizeof(newmodified));
188 
189 }
190 
191 static void initmode(usbmode* mode){
192  memset(mode, 0, sizeof(*mode));
193  mode->light.forceupdate = 1;
194  mode->dpi.forceupdate = 1;
195  initbind(&mode->bind);
196 }
197 
199  if(kb->profile)
200  return;
201  usbprofile* profile = kb->profile = calloc(1, sizeof(usbprofile));
202  for(int i = 0; i < MODE_COUNT; i++)
203  initmode(profile->mode + i);
204  profile->currentmode = profile->mode;
205  profile->lastlight.forceupdate = profile->lastdpi.forceupdate = 1;
206 }
207 
209  if(hwloadprofile(kb, 1))
210  return -1;
211  return 0;
212 }
213 
214 static void freemode(usbmode* mode){
215  freebind(&mode->bind);
216  memset(mode, 0, sizeof(*mode));
217 }
218 
219 void cmd_erase(usbdevice* kb, usbmode* mode, int dummy1, int dummy2, const char* dummy3){
220  (void)dummy1;
221  (void)dummy2;
222  (void)dummy3;
223 
224  pthread_mutex_lock(imutex(kb));
225  freemode(mode);
226  initmode(mode);
227  pthread_mutex_unlock(imutex(kb));
228 }
229 
230 static void _freeprofile(usbdevice* kb){
231  usbprofile* profile = kb->profile;
232  if(!profile)
233  return;
234  // Clear all mode data
235  for(int i = 0; i < MODE_COUNT; i++)
236  freemode(profile->mode + i);
237  free(profile);
238  kb->profile = 0;
239 }
240 
241 void cmd_eraseprofile(usbdevice* kb, usbmode* dummy1, int dummy2, int dummy3, const char* dummy4){
242  (void)dummy1;
243  (void)dummy2;
244  (void)dummy3;
245  (void)dummy4;
246 
247  pthread_mutex_lock(imutex(kb));
248  _freeprofile(kb);
249  allocprofile(kb);
250  pthread_mutex_unlock(imutex(kb));
251 }
252 
254  _freeprofile(kb);
255  // Also free HW profile
256  free(kb->hw);
257  kb->hw = 0;
258 }
259 
260 void hwtonative(usbprofile* profile, hwprofile* hw, int modecount){
261  // Copy the profile name and ID
262  memcpy(profile->name, hw->name[0], PR_NAME_LEN * 2);
263  memcpy(&profile->id, hw->id, sizeof(usbid));
264  // Copy the mode settings
265  for(int i = 0; i < modecount; i++){
266  usbmode* mode = profile->mode + i;
267  memcpy(mode->name, hw->name[i + 1], MD_NAME_LEN * 2);
268  memcpy(&mode->id, hw->id + i + 1, sizeof(usbid));
269  memcpy(&mode->light, hw->light + i, sizeof(lighting));
270  memcpy(&mode->dpi, hw->dpi + i, sizeof(dpiset));
271  // Set a force update on the light/DPI since they've been overwritten
272  mode->light.forceupdate = mode->dpi.forceupdate = 1;
273  }
274  profile->lastlight.forceupdate = profile->lastdpi.forceupdate = 1;
275 }
276 
277 void nativetohw(usbprofile* profile, hwprofile* hw, int modecount){
278  // Copy name and ID
279  memcpy(hw->name[0], profile->name, PR_NAME_LEN * 2);
280  memcpy(hw->id, &profile->id, sizeof(usbid));
281  // Copy the mode settings
282  for(int i = 0; i < modecount; i++){
283  usbmode* mode = profile->mode + i;
284  memcpy(hw->name[i + 1], mode->name, MD_NAME_LEN * 2);
285  memcpy(hw->id + i + 1, &mode->id, sizeof(usbid));
286  memcpy(hw->light + i, &mode->light, sizeof(lighting));
287  memcpy(hw->dpi + i, &mode->dpi, sizeof(dpiset));
288  }
289 }
void initbind(binding *bind)
Definition: input.c:292
lighting lastlight
Definition: structures.h:107
void freeprofile(usbdevice *kb)
Definition: profile.c:253
#define MODE_COUNT
Definition: structures.h:100
usbprofile * profile
Definition: structures.h:221
char * getprofilename(usbprofile *profile)
Definition: profile.c:156
void urlencode2(char *dst, const char *src)
Definition: profile.c:37
char * getmodename(usbmode *mode)
Definition: profile.c:152
usbmode * currentmode
Definition: structures.h:105
int setid(usbid *id, const char *guid)
Definition: profile.c:64
usbmode mode[6]
Definition: structures.h:103
void cmd_id(usbdevice *kb, usbmode *mode, int dummy1, int dummy2, const char *id)
Definition: profile.c:168
void u16enc(char *in, ushort *out, size_t *srclen, size_t *dstlen)
Definition: profile.c:97
static void _freeprofile(usbdevice *kb)
Definition: profile.c:230
ushort name[16]
Definition: structures.h:89
char modified[4]
Definition: structures.h:10
#define MD_NAME_LEN
Definition: structures.h:82
usbid id
Definition: structures.h:111
#define PR_NAME_LEN
Definition: structures.h:99
void cmd_name(usbdevice *kb, usbmode *mode, int dummy1, int dummy2, const char *name)
Definition: profile.c:117
dpiset lastdpi
Definition: structures.h:108
lighting light
Definition: structures.h:84
usbid id[3+1]
Definition: structures.h:123
dpiset dpi
Definition: structures.h:86
char * gethwprofilename(hwprofile *profile)
Definition: profile.c:164
ushort name[16]
Definition: structures.h:110
char * gethwmodename(hwprofile *profile, int index)
Definition: profile.c:160
void cmd_profilename(usbdevice *kb, usbmode *dummy1, int dummy2, int dummy3, const char *name)
Definition: profile.c:128
static iconv_t utf8to16
Definition: profile.c:95
void allocprofile(usbdevice *kb)
Definition: profile.c:198
void urldecode2(char *dst, const char *src)
Definition: profile.c:8
void cmd_profileid(usbdevice *kb, usbmode *mode, int dummy1, int dummy2, const char *id)
Definition: profile.c:179
uchar forceupdate
Definition: structures.h:77
void hwtonative(usbprofile *profile, hwprofile *hw, int modecount)
Definition: profile.c:260
char * getid(usbid *id)
Definition: profile.c:79
dpiset dpi[3]
Definition: structures.h:121
void nativetohw(usbprofile *profile, hwprofile *hw, int modecount)
Definition: profile.c:277
unsigned short ushort
Definition: includes.h:25
char guid[16]
Definition: structures.h:9
static void freemode(usbmode *mode)
Definition: profile.c:214
#define imutex(kb)
Definition: device.h:22
void cmd_erase(usbdevice *kb, usbmode *mode, int dummy1, int dummy2, const char *dummy3)
Definition: profile.c:219
binding bind
Definition: structures.h:85
hwprofile * hw
Definition: structures.h:223
ushort name[3+1][16]
Definition: structures.h:125
void freebind(binding *bind)
Definition: input.c:300
static void initmode(usbmode *mode)
Definition: profile.c:191
static iconv_t utf16to8
Definition: profile.c:95
char * printname(ushort *name, int length)
Definition: profile.c:140
lighting light[3]
Definition: structures.h:120
void u16dec(ushort *in, char *out, size_t *srclen, size_t *dstlen)
Definition: profile.c:105
#define hwloadprofile(kb, apply)
Definition: profile.h:52
uchar forceupdate
Definition: structures.h:69
usbid id
Definition: structures.h:88
void cmd_eraseprofile(usbdevice *kb, usbmode *dummy1, int dummy2, int dummy3, const char *dummy4)
Definition: profile.c:241
int loadprofile(usbdevice *kb)
Definition: profile.c:208