hw_deathadder2013.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. /*
  2. * Lowlevel hardware access for the
  3. * Razer Deathadder2013 mouse
  4. *
  5. * Important notice:
  6. * This hardware driver is based on reverse engineering, only.
  7. *
  8. * Copyright (C) 2007-2010 Michael Buesch <m@bues.ch>
  9. * Copyright (C) 2010 Bernd Michael Helm <deathadder2013@rw23.de>
  10. *
  11. * Deathadder2013 fixes by Tony Crisci <tony@dubstepdish.com>
  12. *
  13. * This program is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU General Public License
  15. * as published by the Free Software Foundation; either version 2
  16. * of the License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. */
  23. #include "hw_deathadder2013.h"
  24. #include "razer_private.h"
  25. #include <errno.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <stdint.h>
  29. #include <string.h>
  30. enum {
  31. DEATHADDER2013_LED_SCROLL = 0,
  32. DEATHADDER2013_LED_LOGO,
  33. DEATHADDER2013_NR_LEDS,
  34. };
  35. enum { /* Misc constants */
  36. DEATHADDER2013_NR_DPIMAPPINGS = 64,
  37. DEATHADDER2013_NR_AXES = 3,
  38. };
  39. struct deathadder2013_command {
  40. uint8_t status;
  41. uint8_t padding0[3];
  42. le16_t command;
  43. le16_t request;
  44. le16_t value0;
  45. le16_t value1;
  46. uint8_t padding1[76];
  47. uint8_t footer;
  48. uint8_t padding2;
  49. } _packed;
  50. struct deathadder2013_private {
  51. struct razer_mouse *m;
  52. /* Firmware version number. */
  53. uint16_t fw_version;
  54. /* The currently set LED states. */
  55. bool led_states[DEATHADDER2013_NR_LEDS];
  56. /* The currently set frequency. */
  57. enum razer_mouse_freq frequency;
  58. /* The currently set resolution. */
  59. struct razer_mouse_dpimapping *cur_dpimapping_X;
  60. struct razer_mouse_dpimapping *cur_dpimapping_Y;
  61. struct razer_mouse_profile profile;
  62. struct razer_mouse_dpimapping dpimapping[DEATHADDER2013_NR_DPIMAPPINGS];
  63. struct razer_axis axes[DEATHADDER2013_NR_AXES];
  64. bool commit_pending;
  65. };
  66. static void deathadder2013_command_init(struct deathadder2013_command *cmd)
  67. {
  68. memset(cmd, 0, sizeof(*cmd));
  69. }
  70. static int deathadder2013_usb_write(struct deathadder2013_private *priv,
  71. int request, int command,
  72. void *buf, size_t size)
  73. {
  74. int err;
  75. err = libusb_control_transfer(priv->m->usb_ctx->h,
  76. LIBUSB_ENDPOINT_OUT |
  77. LIBUSB_REQUEST_TYPE_CLASS |
  78. LIBUSB_RECIPIENT_INTERFACE, request,
  79. command, 0, (unsigned char *)buf, size,
  80. RAZER_USB_TIMEOUT);
  81. if (err < 0 || (size_t)err != size) {
  82. razer_error("razer-deathadder2013: "
  83. "USB write 0x%02X 0x%02X failed: %d\n",
  84. request, command, err);
  85. return err;
  86. }
  87. return 0;
  88. }
  89. static int deathadder2013_usb_read(struct deathadder2013_private *priv,
  90. int request, int command,
  91. void *buf, size_t size)
  92. {
  93. int err, try;
  94. for (try = 0; try < 3; try++) {
  95. err = libusb_control_transfer(priv->m->usb_ctx->h,
  96. LIBUSB_ENDPOINT_IN |
  97. LIBUSB_REQUEST_TYPE_CLASS |
  98. LIBUSB_RECIPIENT_INTERFACE,
  99. request, command, 0, buf, size,
  100. RAZER_USB_TIMEOUT);
  101. if (err >= 0 && (size_t)err == size)
  102. break;
  103. }
  104. if (err < 0 || (size_t)err != size) {
  105. razer_error("razer-deathadder2013: USB read 0x%02X 0x%02X failed: %d\n",
  106. request, command, err);
  107. return err;
  108. }
  109. return 0;
  110. }
  111. static int deathadder2013_send_command(struct deathadder2013_private *priv,
  112. struct deathadder2013_command *cmd)
  113. {
  114. int err, i;
  115. /* commands seem to fail less often when you do them a few times. */
  116. for (i = 0; i < 3; i++) {
  117. cmd->status = 0x00;
  118. err = deathadder2013_usb_write(priv,
  119. LIBUSB_REQUEST_SET_CONFIGURATION,
  120. 0x300, cmd, sizeof(*cmd));
  121. if (err)
  122. return err;
  123. err = deathadder2013_usb_read(priv,
  124. LIBUSB_REQUEST_CLEAR_FEATURE,
  125. 0x300, cmd, sizeof(*cmd));
  126. if (err)
  127. return err;
  128. if (cmd->status != 3 &&
  129. cmd->status != 2 && cmd->status != 1 && cmd->status != 0) {
  130. razer_error("razer-deathadder2013: Command %04X/%04X failed with %02X\n",
  131. le16_to_cpu(cmd->command),
  132. le16_to_cpu(cmd->request), cmd->status);
  133. }
  134. razer_msleep(35);
  135. }
  136. return 0;
  137. }
  138. static int deathadder2013_read_fw_ver(struct deathadder2013_private *priv)
  139. {
  140. struct deathadder2013_command cmd;
  141. uint16_t ver;
  142. int err;
  143. unsigned int i;
  144. /* Poke the device several times until it responds with a
  145. * valid version number */
  146. for (i = 0; i < 10; i++) {
  147. deathadder2013_command_init(&cmd);
  148. cmd.status = 0x00;
  149. cmd.command = cpu_to_le16(0x0400);
  150. cmd.request = cpu_to_le16(0x8700);
  151. cmd.footer = 0x83;
  152. err = deathadder2013_send_command(priv, &cmd);
  153. ver = be16_to_cpu((be16_t) cmd.value0);
  154. if (!err && (ver & 0xFF00) != 0)
  155. return ver;
  156. razer_msleep(150);
  157. }
  158. razer_error("razer-deathadder2013: Failed to read firmware version\n");
  159. /* sometimes it just won't read the firmware version. */
  160. return 0;
  161. }
  162. static int deathadder2013_do_commit(struct deathadder2013_private *priv)
  163. {
  164. struct deathadder2013_command cmd;
  165. unsigned int xres, yres, freq;
  166. int err;
  167. /* Set the resolution. */
  168. deathadder2013_command_init(&cmd);
  169. cmd.command = cpu_to_le16(0x0300);
  170. cmd.request = cpu_to_le16(0x0104);
  171. xres = (((unsigned int)priv->cur_dpimapping_X->res[RAZER_DIM_0] / 100) - 1) * 4;
  172. yres = (((unsigned int)priv->cur_dpimapping_Y->res[RAZER_DIM_0] / 100) - 1) * 4;
  173. cmd.value0 = cpu_to_le16(xres | (yres << 8));
  174. cmd.footer = 0x06;
  175. err = deathadder2013_send_command(priv, &cmd);
  176. if (err)
  177. return err;
  178. /* Set the scroll wheel and buttons LEDs. */
  179. deathadder2013_command_init(&cmd);
  180. cmd.command = cpu_to_le16(0x0300);
  181. cmd.request = cpu_to_le16(0x0003);
  182. cmd.value0 = cpu_to_le16(0x0101);
  183. if (priv->led_states[DEATHADDER2013_LED_SCROLL]) {
  184. cmd.value1 = cpu_to_le16(0x0001);
  185. cmd.footer = 0x01;
  186. } else {
  187. cmd.value1 = cpu_to_le16(0x0000);
  188. cmd.footer = 0x00;
  189. }
  190. err = deathadder2013_send_command(priv, &cmd);
  191. if (err)
  192. return err;
  193. /* Set the logo LED. */
  194. deathadder2013_command_init(&cmd);
  195. cmd.command = cpu_to_le16(0x0300);
  196. cmd.request = cpu_to_le16(0x0003);
  197. cmd.value0 = cpu_to_le16(0x0401);
  198. if (priv->led_states[DEATHADDER2013_LED_LOGO]) {
  199. cmd.value1 = cpu_to_le16(1);
  200. cmd.footer = 0x04;
  201. } else {
  202. cmd.value1 = cpu_to_le16(0);
  203. cmd.footer = 0x05;
  204. }
  205. err = deathadder2013_send_command(priv, &cmd);
  206. if (err)
  207. return err;
  208. /* Set scan frequency. */
  209. switch (priv->frequency) {
  210. case RAZER_MOUSE_FREQ_125HZ:
  211. freq = 8;
  212. cmd.footer = 0x0C;
  213. break;
  214. case RAZER_MOUSE_FREQ_500HZ:
  215. freq = 2;
  216. cmd.footer = 0x06;
  217. break;
  218. case RAZER_MOUSE_FREQ_1000HZ:
  219. case RAZER_MOUSE_FREQ_UNKNOWN:
  220. freq = 1;
  221. cmd.footer = 0x05;
  222. break;
  223. default:
  224. return -EINVAL;
  225. }
  226. deathadder2013_command_init(&cmd);
  227. cmd.command = cpu_to_le16(0x0100);
  228. cmd.request = cpu_to_le16(0x0500);
  229. cmd.value0 = cpu_to_le16(freq);
  230. err = deathadder2013_send_command(priv, &cmd);
  231. if (err)
  232. return err;
  233. return 0;
  234. }
  235. static int deathadder2013_get_fw_version(struct razer_mouse *m)
  236. {
  237. struct deathadder2013_private *priv = m->drv_data;
  238. return priv->fw_version;
  239. }
  240. static int deathadder2013_commit(struct razer_mouse *m, int force)
  241. {
  242. struct deathadder2013_private *priv = m->drv_data;
  243. int err = 0;
  244. if (!m->claim_count)
  245. return -EBUSY;
  246. if (priv->commit_pending || force) {
  247. err = deathadder2013_do_commit(priv);
  248. if (!err)
  249. priv->commit_pending = 0;
  250. }
  251. return err;
  252. }
  253. static int deathadder2013_led_toggle(struct razer_led *led,
  254. enum razer_led_state new_state)
  255. {
  256. struct razer_mouse *m = led->u.mouse;
  257. struct deathadder2013_private *priv = m->drv_data;
  258. if (led->id >= DEATHADDER2013_NR_LEDS)
  259. return -EINVAL;
  260. if ((new_state != RAZER_LED_OFF) && (new_state != RAZER_LED_ON))
  261. return -EINVAL;
  262. if (!priv->m->claim_count)
  263. return -EBUSY;
  264. priv->led_states[led->id] = new_state;
  265. priv->commit_pending = 1;
  266. return 0;
  267. }
  268. static int deathadder2013_get_leds(struct razer_mouse *m,
  269. struct razer_led **leds_list)
  270. {
  271. struct deathadder2013_private *priv = m->drv_data;
  272. struct razer_led *scroll, *logo;
  273. scroll = zalloc(sizeof(struct razer_led));
  274. if (!scroll)
  275. return -ENOMEM;
  276. logo = zalloc(sizeof(struct razer_led));
  277. if (!logo) {
  278. free(scroll);
  279. return -ENOMEM;
  280. }
  281. scroll->name = "Scrollwheel";
  282. scroll->id = DEATHADDER2013_LED_SCROLL;
  283. scroll->state = priv->led_states[DEATHADDER2013_LED_SCROLL];
  284. scroll->toggle_state = deathadder2013_led_toggle;
  285. scroll->u.mouse = m;
  286. logo->name = "GlowingLogo";
  287. logo->id = DEATHADDER2013_LED_LOGO;
  288. logo->state = priv->led_states[DEATHADDER2013_LED_LOGO];
  289. logo->toggle_state = deathadder2013_led_toggle;
  290. logo->u.mouse = m;
  291. /* Link the list */
  292. *leds_list = scroll;
  293. scroll->next = logo;
  294. logo->next = NULL;
  295. return DEATHADDER2013_NR_LEDS;
  296. }
  297. static int deathadder2013_supported_freqs(struct razer_mouse *m,
  298. enum razer_mouse_freq **freq_list)
  299. {
  300. enum razer_mouse_freq *list;
  301. const int count = 3;
  302. list = zalloc(sizeof(*list) * count);
  303. if (!list)
  304. return -ENOMEM;
  305. list[0] = RAZER_MOUSE_FREQ_125HZ;
  306. list[1] = RAZER_MOUSE_FREQ_500HZ;
  307. list[2] = RAZER_MOUSE_FREQ_1000HZ;
  308. *freq_list = list;
  309. return count;
  310. }
  311. static enum razer_mouse_freq deathadder2013_get_freq(struct razer_mouse_profile
  312. *p)
  313. {
  314. struct deathadder2013_private *priv = p->mouse->drv_data;
  315. return priv->frequency;
  316. }
  317. static int deathadder2013_set_freq(struct razer_mouse_profile *p,
  318. enum razer_mouse_freq freq)
  319. {
  320. struct deathadder2013_private *priv = p->mouse->drv_data;
  321. if (!priv->m->claim_count)
  322. return -EBUSY;
  323. priv->frequency = freq;
  324. priv->commit_pending = 1;
  325. return 0;
  326. }
  327. static int deathadder2013_supported_axes(struct razer_mouse *m,
  328. struct razer_axis **axes_list)
  329. {
  330. struct deathadder2013_private *priv = m->drv_data;
  331. *axes_list = priv->axes;
  332. return ARRAY_SIZE(priv->axes);
  333. }
  334. static int deathadder2013_supported_resolutions(struct razer_mouse *m,
  335. enum razer_mouse_res **res_list)
  336. {
  337. enum razer_mouse_res *list;
  338. unsigned int i;
  339. const unsigned int count = DEATHADDER2013_NR_DPIMAPPINGS;
  340. list = zalloc(sizeof(*list) * count);
  341. if (!list)
  342. return -ENOMEM;
  343. for (i = 0; i < count; i++)
  344. list[i] = (i + 1) * 100;
  345. *res_list = list;
  346. return count;
  347. }
  348. static struct razer_mouse_profile *deathadder2013_get_profiles(struct
  349. razer_mouse *m)
  350. {
  351. struct deathadder2013_private *priv = m->drv_data;
  352. return &priv->profile;
  353. }
  354. static int deathadder2013_supported_dpimappings(struct razer_mouse *m,
  355. struct razer_mouse_dpimapping
  356. **res_ptr)
  357. {
  358. struct deathadder2013_private *priv = m->drv_data;
  359. *res_ptr = &priv->dpimapping[0];
  360. return ARRAY_SIZE(priv->dpimapping);
  361. }
  362. static struct razer_mouse_dpimapping *deathadder2013_get_dpimapping(struct razer_mouse_profile *p,
  363. struct razer_axis *axis)
  364. {
  365. struct deathadder2013_private *priv = p->mouse->drv_data;
  366. if (!axis)
  367. axis = &priv->axes[0];
  368. if (axis->id == 0)
  369. return priv->cur_dpimapping_X;
  370. if (axis->id == 1)
  371. return priv->cur_dpimapping_Y;
  372. return NULL;
  373. }
  374. static int deathadder2013_set_dpimapping(struct razer_mouse_profile *p,
  375. struct razer_axis *axis,
  376. struct razer_mouse_dpimapping *d)
  377. {
  378. struct deathadder2013_private *priv = p->mouse->drv_data;
  379. if (!priv->m->claim_count)
  380. return -EBUSY;
  381. if (axis && axis->id >= ARRAY_SIZE(priv->axes))
  382. return -EINVAL;
  383. if (axis) {
  384. if (axis->id == 0)
  385. priv->cur_dpimapping_X = d;
  386. else if (axis->id == 1)
  387. priv->cur_dpimapping_Y = d;
  388. else
  389. return -EINVAL;
  390. } else {
  391. priv->cur_dpimapping_X = d;
  392. priv->cur_dpimapping_Y = d;
  393. }
  394. priv->commit_pending = 1;
  395. return 0;
  396. }
  397. int razer_deathadder2013_init(struct razer_mouse *m,
  398. struct libusb_device *usbdev)
  399. {
  400. struct deathadder2013_private *priv;
  401. unsigned int i;
  402. int fwver, err;
  403. BUILD_BUG_ON(sizeof(struct deathadder2013_command) != 90);
  404. priv = zalloc(sizeof(struct deathadder2013_private));
  405. if (!priv)
  406. return -ENOMEM;
  407. priv->m = m;
  408. m->drv_data = priv;
  409. err = razer_usb_add_used_interface(m->usb_ctx, 0, 0);
  410. if (err)
  411. goto err_free;
  412. err = m->claim(m);
  413. if (err) {
  414. razer_error("hw_deathadder2013: Failed to claim device\n");
  415. goto err_free;
  416. }
  417. /* Fetch firmware version */
  418. fwver = deathadder2013_read_fw_ver(priv);
  419. if (fwver < 0) {
  420. err = fwver;
  421. goto err_release;
  422. }
  423. priv->fw_version = fwver;
  424. priv->frequency = RAZER_MOUSE_FREQ_1000HZ;
  425. for (i = 0; i < DEATHADDER2013_NR_LEDS; i++)
  426. priv->led_states[i] = RAZER_LED_ON;
  427. priv->profile.nr = 0;
  428. priv->profile.get_freq = deathadder2013_get_freq;
  429. priv->profile.set_freq = deathadder2013_set_freq;
  430. priv->profile.get_dpimapping = deathadder2013_get_dpimapping;
  431. priv->profile.set_dpimapping = deathadder2013_set_dpimapping;
  432. priv->profile.mouse = m;
  433. for (i = 0; i < DEATHADDER2013_NR_DPIMAPPINGS; i++) {
  434. priv->dpimapping[i].nr = i;
  435. priv->dpimapping[i].res[RAZER_DIM_0] = (i + 1) * 100;
  436. if (priv->dpimapping[i].res[RAZER_DIM_0] == 1000) {
  437. priv->cur_dpimapping_X = &priv->dpimapping[i];
  438. priv->cur_dpimapping_Y = &priv->dpimapping[i];
  439. }
  440. priv->dpimapping[i].dimension_mask = (1 << RAZER_DIM_0);
  441. priv->dpimapping[i].change = NULL;
  442. priv->dpimapping[i].mouse = m;
  443. }
  444. razer_init_axes(&priv->axes[0],
  445. "X", RAZER_AXIS_INDEPENDENT_DPIMAPPING,
  446. "Y", RAZER_AXIS_INDEPENDENT_DPIMAPPING, "Scroll", 0);
  447. m->type = RAZER_MOUSETYPE_DEATHADDER;
  448. razer_generic_usb_gen_idstr(usbdev, m->usb_ctx->h,
  449. "DeathAdder 2013 Edition", 1, NULL,
  450. m->idstr);
  451. m->get_fw_version = deathadder2013_get_fw_version;
  452. m->commit = deathadder2013_commit;
  453. m->global_get_leds = deathadder2013_get_leds;
  454. m->get_profiles = deathadder2013_get_profiles;
  455. m->supported_axes = deathadder2013_supported_axes;
  456. m->supported_resolutions = deathadder2013_supported_resolutions;
  457. m->supported_freqs = deathadder2013_supported_freqs;
  458. m->supported_dpimappings = deathadder2013_supported_dpimappings;
  459. m->release(m);
  460. return 0;
  461. err_release:
  462. m->release(m);
  463. err_free:
  464. free(priv);
  465. return err;
  466. }
  467. void razer_deathadder2013_release(struct razer_mouse *m)
  468. {
  469. struct deathadder2013_private *priv = m->drv_data;
  470. free(priv);
  471. }