profile_emulation.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * Razer device access library
  3. * Profile emulation
  4. *
  5. * Copyright (C) 2011 Michael Buesch <m@bues.ch>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. */
  17. #include "profile_emulation.h"
  18. static int mouse_profemu_commit(struct razer_mouse_profile_emu *emu)
  19. {
  20. struct razer_mouse_profile *hw_profile = emu->hw_profile;
  21. unsigned int active_prof_nr = emu->active_profile->nr;
  22. struct razer_mouse_profile_emu_data *data;
  23. struct razer_mouse *mouse = emu->mouse;
  24. unsigned int i;
  25. int err;
  26. if (WARN_ON(active_prof_nr >= ARRAY_SIZE(emu->data)))
  27. return -EINVAL;
  28. data = &emu->data[active_prof_nr];
  29. err = mouse->claim(mouse);
  30. if (err) {
  31. razer_error("profile emulation: Failed to claim mouse\n");
  32. return err;
  33. }
  34. if (hw_profile->set_dpimapping) {
  35. struct razer_axis *axes = NULL;
  36. if (mouse->supported_axes) {
  37. err = mouse->supported_axes(mouse, &axes);
  38. if (err < 0)
  39. goto error;
  40. WARN_ON((unsigned int)err != data->nr_dpimappings);
  41. }
  42. for (i = 0; i < data->nr_dpimappings; i++) {
  43. if (!data->dpimappings[i])
  44. continue;
  45. err = hw_profile->set_dpimapping(
  46. hw_profile,
  47. axes ? &axes[i] : NULL,
  48. data->dpimappings[i]);
  49. if (err)
  50. goto error;
  51. }
  52. }
  53. if (hw_profile->set_button_function) {
  54. struct razer_button *buttons = NULL;
  55. if (mouse->supported_buttons) {
  56. err = mouse->supported_buttons(mouse, &buttons);
  57. if (err < 0)
  58. goto error;
  59. WARN_ON((unsigned int)err != data->nr_butfuncs);
  60. }
  61. for (i = 0; i < data->nr_butfuncs; i++) {
  62. if (!data->butfuncs[i])
  63. continue;
  64. err = hw_profile->set_button_function(
  65. hw_profile,
  66. buttons ? &buttons[i] : NULL,
  67. data->butfuncs[i]);
  68. if (err)
  69. goto error;
  70. }
  71. }
  72. if (hw_profile->set_freq) {
  73. err = hw_profile->set_freq(hw_profile, data->freq);
  74. if (err)
  75. goto error;
  76. }
  77. mouse->release(mouse);
  78. razer_debug("profile emulation: Committed active profile\n");
  79. return 0;
  80. error:
  81. razer_error("profile emulation: Failed to commit settings\n");
  82. mouse->release(mouse);
  83. return err;
  84. }
  85. static const razer_utf16_t * mouse_profemu_get_name(struct razer_mouse_profile *p)
  86. {
  87. struct razer_mouse *mouse = p->mouse;
  88. struct razer_mouse_profile_emu *emu = mouse->profemu;
  89. if (WARN_ON(p->nr >= ARRAY_SIZE(emu->profiles)))
  90. return NULL;
  91. return emu->data[p->nr].name;
  92. }
  93. static int mouse_profemu_set_name(struct razer_mouse_profile *p,
  94. const razer_utf16_t *new_name)
  95. {
  96. struct razer_mouse *mouse = p->mouse;
  97. struct razer_mouse_profile_emu *emu = mouse->profemu;
  98. if (WARN_ON(p->nr >= ARRAY_SIZE(emu->profiles)))
  99. return -EINVAL;
  100. razer_utf16_cpy(emu->data[p->nr].name, new_name, PROFEMU_NAME_MAX);
  101. return 0;
  102. }
  103. static enum razer_mouse_freq mouse_profemu_get_freq(struct razer_mouse_profile *p)
  104. {
  105. struct razer_mouse *mouse = p->mouse;
  106. struct razer_mouse_profile_emu *emu = mouse->profemu;
  107. if (WARN_ON(p->nr >= ARRAY_SIZE(emu->profiles)))
  108. return RAZER_MOUSE_FREQ_UNKNOWN;
  109. return emu->data[p->nr].freq;
  110. }
  111. static int mouse_profemu_set_freq(struct razer_mouse_profile *p,
  112. enum razer_mouse_freq freq)
  113. {
  114. struct razer_mouse *mouse = p->mouse;
  115. struct razer_mouse_profile_emu *emu = mouse->profemu;
  116. if (WARN_ON(p->nr >= ARRAY_SIZE(emu->profiles)))
  117. return -EINVAL;
  118. emu->data[p->nr].freq = freq;
  119. if (p == emu->active_profile)
  120. return mouse_profemu_commit(emu);
  121. return 0;
  122. }
  123. static struct razer_mouse_dpimapping * mouse_profemu_get_dpimapping(
  124. struct razer_mouse_profile *p,
  125. struct razer_axis *axis)
  126. {
  127. struct razer_mouse *mouse = p->mouse;
  128. struct razer_mouse_profile_emu *emu = mouse->profemu;
  129. struct razer_mouse_profile_emu_data *data;
  130. unsigned int axis_index;
  131. if (WARN_ON(p->nr >= ARRAY_SIZE(emu->profiles)))
  132. return NULL;
  133. data = &emu->data[p->nr];
  134. axis_index = axis ? axis->id : 0;
  135. if (WARN_ON(axis_index >= ARRAY_SIZE(data->dpimappings)))
  136. return NULL;
  137. return data->dpimappings[axis_index];
  138. }
  139. static int mouse_profemu_set_dpimapping(struct razer_mouse_profile *p,
  140. struct razer_axis *axis,
  141. struct razer_mouse_dpimapping *d)
  142. {
  143. struct razer_mouse *mouse = p->mouse;
  144. struct razer_mouse_profile_emu *emu = mouse->profemu;
  145. struct razer_mouse_profile_emu_data *data;
  146. unsigned int i;
  147. if (WARN_ON(p->nr >= ARRAY_SIZE(emu->profiles)))
  148. return -EINVAL;
  149. data = &emu->data[p->nr];
  150. if (axis) {
  151. if (WARN_ON(axis->id >= ARRAY_SIZE(data->dpimappings)))
  152. return -EINVAL;
  153. data->dpimappings[axis->id] = d;
  154. } else {
  155. for (i = 0; i < data->nr_dpimappings; i++) {
  156. if (data->dpimappings[i])
  157. data->dpimappings[i] = d;
  158. }
  159. }
  160. if (p == emu->active_profile)
  161. return mouse_profemu_commit(emu);
  162. return 0;
  163. }
  164. static struct razer_button_function * mouse_profemu_get_button_function(
  165. struct razer_mouse_profile *p,
  166. struct razer_button *b)
  167. {
  168. struct razer_mouse *mouse = p->mouse;
  169. struct razer_mouse_profile_emu *emu = mouse->profemu;
  170. struct razer_mouse_profile_emu_data *data;
  171. if (WARN_ON(p->nr >= ARRAY_SIZE(emu->profiles)))
  172. return NULL;
  173. data = &emu->data[p->nr];
  174. if (WARN_ON(b->id >= ARRAY_SIZE(data->butfuncs)))
  175. return NULL;
  176. return data->butfuncs[b->id];
  177. }
  178. static int mouse_profemu_set_button_function(struct razer_mouse_profile *p,
  179. struct razer_button *b,
  180. struct razer_button_function *f)
  181. {
  182. struct razer_mouse *mouse = p->mouse;
  183. struct razer_mouse_profile_emu *emu = mouse->profemu;
  184. struct razer_mouse_profile_emu_data *data;
  185. if (WARN_ON(p->nr >= ARRAY_SIZE(emu->profiles)))
  186. return -EINVAL;
  187. data = &emu->data[p->nr];
  188. if (WARN_ON(b->id >= ARRAY_SIZE(data->butfuncs)))
  189. return -EINVAL;
  190. data->butfuncs[b->id] = f;
  191. if (p == emu->active_profile)
  192. return mouse_profemu_commit(emu);
  193. return 0;
  194. }
  195. static struct razer_mouse_profile * mouse_profemu_get(struct razer_mouse *m)
  196. {
  197. return &m->profemu->profiles[0];
  198. }
  199. static struct razer_mouse_profile * mouse_profemu_get_active(struct razer_mouse *m)
  200. {
  201. return m->profemu->active_profile;
  202. }
  203. static int mouse_profemu_set_active(struct razer_mouse *m,
  204. struct razer_mouse_profile *p)
  205. {
  206. struct razer_mouse_profile_emu *emu = m->profemu;
  207. if (p == emu->active_profile)
  208. return 0;
  209. emu->active_profile = p;
  210. return mouse_profemu_commit(emu);
  211. }
  212. static void mouse_profemu_initial_name(razer_utf16_t *namebuf, unsigned int profnr)
  213. {
  214. char name[PROFEMU_NAME_MAX + 1];
  215. switch (profnr) {
  216. case 0:
  217. snprintf(name, sizeof(name), "Desktop");
  218. break;
  219. case 1:
  220. snprintf(name, sizeof(name), "FPS gaming");
  221. break;
  222. case 2:
  223. snprintf(name, sizeof(name), "RPG gaming");
  224. break;
  225. case 3:
  226. snprintf(name, sizeof(name), "Generic gaming");
  227. break;
  228. case 4:
  229. snprintf(name, sizeof(name), "CAD");
  230. break;
  231. default:
  232. snprintf(name, sizeof(name), "Profile %u", profnr + 1);
  233. }
  234. razer_ascii_to_utf16(namebuf, PROFEMU_NAME_MAX, name);
  235. }
  236. int razer_mouse_init_profile_emulation(struct razer_mouse *m)
  237. {
  238. struct razer_mouse_profile_emu *emu;
  239. struct razer_mouse_profile_emu_data *data;
  240. struct razer_mouse_profile *prof, *hw_profile;
  241. unsigned int i, j;
  242. int err;
  243. struct razer_axis *axes = NULL;
  244. int nr_axes = 1;
  245. struct razer_button *buttons = NULL;
  246. int nr_buttons = 0;
  247. emu = zalloc(sizeof(*emu));
  248. if (!emu)
  249. return -ENOMEM;
  250. emu->mouse = m;
  251. hw_profile = m->get_profiles(m);
  252. emu->hw_profile = hw_profile;
  253. if (WARN_ON(!emu->hw_profile))
  254. goto err_free;
  255. if (m->supported_axes) {
  256. nr_axes = m->supported_axes(m, &axes);
  257. if (WARN_ON(nr_axes < 0))
  258. goto err_free;
  259. }
  260. if (m->supported_buttons) {
  261. nr_buttons = m->supported_buttons(m, &buttons);
  262. if (WARN_ON(nr_buttons < 0))
  263. goto err_free;
  264. }
  265. for (i = 0; i < ARRAY_SIZE(emu->profiles); i++) {
  266. prof = &emu->profiles[i];
  267. data = &emu->data[i];
  268. prof->mouse = m;
  269. prof->nr = i;
  270. prof->get_name = mouse_profemu_get_name;
  271. prof->set_name = mouse_profemu_set_name;
  272. /* Assign callbacks, if the driver supports the feature. */
  273. //TODO LEDs
  274. if (hw_profile->get_freq)
  275. prof->get_freq = mouse_profemu_get_freq;
  276. if (hw_profile->set_freq)
  277. prof->set_freq = mouse_profemu_set_freq;
  278. if (hw_profile->get_dpimapping)
  279. prof->get_dpimapping = mouse_profemu_get_dpimapping;
  280. if (hw_profile->set_dpimapping)
  281. prof->set_dpimapping = mouse_profemu_set_dpimapping;
  282. if (hw_profile->get_button_function)
  283. prof->get_button_function = mouse_profemu_get_button_function;
  284. if (hw_profile->set_button_function)
  285. prof->set_button_function = mouse_profemu_set_button_function;
  286. /* Load initial settings */
  287. mouse_profemu_initial_name(data->name, i);
  288. if (hw_profile->get_freq)
  289. data->freq = hw_profile->get_freq(hw_profile);
  290. if (hw_profile->get_dpimapping) {
  291. for (j = 0; j < (unsigned int)nr_axes; j++) {
  292. if (WARN_ON(j >= ARRAY_SIZE(data->dpimappings)))
  293. break;
  294. if (!axes || (axes[j].flags & RAZER_AXIS_INDEPENDENT_DPIMAPPING)) {
  295. data->dpimappings[j] = hw_profile->get_dpimapping(
  296. hw_profile,
  297. axes ? &axes[j] : NULL);
  298. }
  299. }
  300. data->nr_dpimappings = j;
  301. }
  302. if (hw_profile->get_button_function) {
  303. for (j = 0; j < (unsigned int)nr_buttons; j++) {
  304. if (WARN_ON(j >= ARRAY_SIZE(data->butfuncs)))
  305. break;
  306. data->butfuncs[j] = hw_profile->get_button_function(
  307. hw_profile,
  308. buttons ? &buttons[j] : NULL);
  309. }
  310. data->nr_butfuncs = j;
  311. }
  312. }
  313. emu->active_profile = &emu->profiles[0];
  314. err = mouse_profemu_commit(emu);
  315. if (err)
  316. goto err_free;
  317. m->nr_profiles = ARRAY_SIZE(emu->profiles);
  318. m->get_profiles = mouse_profemu_get;
  319. m->get_active_profile = mouse_profemu_get_active;
  320. m->set_active_profile = mouse_profemu_set_active;
  321. m->profemu = emu;
  322. m->flags |= RAZER_MOUSEFLG_PROFEMU;
  323. razer_debug("Mouse profile emulation initialized for %s\n", m->idstr);
  324. return 0;
  325. err_free:
  326. razer_free(emu, sizeof(*emu));
  327. return -EINVAL;
  328. }
  329. void razer_mouse_exit_profile_emulation(struct razer_mouse *m)
  330. {
  331. struct razer_mouse_profile_emu *emu;
  332. if (!(m->flags & RAZER_MOUSEFLG_PROFEMU))
  333. return;
  334. emu = m->profemu;
  335. m->nr_profiles = 0;
  336. m->get_profiles = NULL;
  337. m->get_active_profile = NULL;
  338. m->set_active_profile = NULL;
  339. m->profemu = NULL;
  340. m->flags &= ~RAZER_MOUSEFLG_PROFEMU;
  341. razer_free(emu, sizeof(*emu));
  342. }