hw_copperhead.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. /*
  2. * Lowlevel hardware access for the
  3. * Razer Copperhead mouse
  4. *
  5. * Important notice:
  6. * This hardware driver is based on reverse engineering only.
  7. *
  8. * Copyright (C) 2009-2016 Michael Buesch <m@bues.ch>
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. */
  20. #include "hw_copperhead.h"
  21. #include "razer_private.h"
  22. #include "buttonmapping.h"
  23. #include <errno.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <stdint.h>
  27. #include <string.h>
  28. enum { /* Misc constants */
  29. COPPERHEAD_NR_PROFILES = 5,
  30. COPPERHEAD_NR_DPIMAPPINGS = 4,
  31. };
  32. /* The wire protocol data structures... */
  33. enum copperhead_phys_button {
  34. /* Physical button IDs */
  35. COPPERHEAD_PHYSBUT_LEFT = 0x01, /* Left button */
  36. COPPERHEAD_PHYSBUT_RIGHT, /* Right button */
  37. COPPERHEAD_PHYSBUT_MIDDLE, /* Middle button */
  38. COPPERHEAD_PHYSBUT_LFRONT, /* Left side, front button */
  39. COPPERHEAD_PHYSBUT_LREAR, /* Left side, rear button */
  40. COPPERHEAD_PHYSBUT_RFRONT, /* Right side, front button */
  41. COPPERHEAD_PHYSBUT_RREAR, /* Right side, rear button */
  42. NR_COPPERHEAD_PHYSBUT = 7, /* Number of physical buttons */
  43. };
  44. struct copperhead_profcfg_cmd {
  45. le16_t packetlength;
  46. le16_t magic;
  47. le16_t profilenr;
  48. le16_t reply_packetlength; /* Only valid for read data */
  49. le16_t reply_magic; /* Only valid for read data */
  50. le16_t reply_profilenr;
  51. uint8_t dpisel;
  52. uint8_t freq;
  53. uint8_t buttonmap[48 * NR_COPPERHEAD_PHYSBUT - 4];
  54. le16_t checksum;
  55. } _packed;
  56. #define COPPERHEAD_PROFCFG_MAGIC cpu_to_le16(0x0002)
  57. struct copperhead_buttons {
  58. struct razer_buttonmapping mapping[NR_COPPERHEAD_PHYSBUT];
  59. };
  60. struct copperhead_private {
  61. struct razer_mouse *m;
  62. uint16_t fw_version;
  63. /* The active profile. */
  64. struct razer_mouse_profile *cur_profile;
  65. /* Profile configuration (one per profile). */
  66. struct razer_mouse_profile profiles[COPPERHEAD_NR_PROFILES];
  67. /* The active DPI mapping; per profile. */
  68. struct razer_mouse_dpimapping *cur_dpimapping[COPPERHEAD_NR_PROFILES];
  69. /* The possible DPI mappings. */
  70. struct razer_mouse_dpimapping dpimappings[COPPERHEAD_NR_DPIMAPPINGS];
  71. /* The active scan frequency; per profile. */
  72. enum razer_mouse_freq cur_freq[COPPERHEAD_NR_PROFILES];
  73. /* The active button mapping; per profile. */
  74. struct copperhead_buttons buttons[COPPERHEAD_NR_PROFILES];
  75. bool commit_pending;
  76. struct razer_event_spacing commit_spacing;
  77. };
  78. /* A list of physical buttons on the device. */
  79. static struct razer_button copperhead_physical_buttons[] = {
  80. { .id = COPPERHEAD_PHYSBUT_LEFT, .name = "Leftclick", },
  81. { .id = COPPERHEAD_PHYSBUT_RIGHT, .name = "Rightclick", },
  82. { .id = COPPERHEAD_PHYSBUT_MIDDLE, .name = "Middleclick", },
  83. { .id = COPPERHEAD_PHYSBUT_LFRONT, .name = "Leftside front", },
  84. { .id = COPPERHEAD_PHYSBUT_LREAR, .name = "Leftside rear", },
  85. { .id = COPPERHEAD_PHYSBUT_RFRONT, .name = "Rightside front", },
  86. { .id = COPPERHEAD_PHYSBUT_RREAR, .name = "Rightside rear", },
  87. };
  88. /* A list of possible button functions. */
  89. static struct razer_button_function copperhead_button_functions[] = {
  90. BUTTONFUNC_LEFT,
  91. BUTTONFUNC_RIGHT,
  92. BUTTONFUNC_MIDDLE,
  93. BUTTONFUNC_PROFDOWN,
  94. BUTTONFUNC_PROFUP,
  95. BUTTONFUNC_DPIUP,
  96. BUTTONFUNC_DPIDOWN,
  97. BUTTONFUNC_DPI1,
  98. BUTTONFUNC_DPI2,
  99. BUTTONFUNC_DPI3,
  100. BUTTONFUNC_DPI4,
  101. BUTTONFUNC_DPI5,
  102. BUTTONFUNC_WIN5,
  103. BUTTONFUNC_WIN4,
  104. BUTTONFUNC_SCROLLUP,
  105. BUTTONFUNC_SCROLLDWN,
  106. };
  107. static int copperhead_usb_write(struct copperhead_private *priv,
  108. int request, int command, int index,
  109. void *buf, size_t size)
  110. {
  111. int err;
  112. err = libusb_control_transfer(
  113. priv->m->usb_ctx->h,
  114. LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS |
  115. LIBUSB_RECIPIENT_OTHER,
  116. request, command, index,
  117. (unsigned char *)buf, size, RAZER_USB_TIMEOUT);
  118. if (err < 0 || (size_t)err != size) {
  119. razer_error("razer-copperhead: "
  120. "USB write 0x%02X 0x%02X 0x%02X failed: %d\n",
  121. request, command, index, err);
  122. return -EIO;
  123. }
  124. return 0;
  125. }
  126. static int copperhead_usb_read(struct copperhead_private *priv,
  127. int request, int command, int index,
  128. void *buf, size_t size)
  129. {
  130. int err;
  131. err = libusb_control_transfer(
  132. priv->m->usb_ctx->h,
  133. LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS |
  134. LIBUSB_RECIPIENT_OTHER,
  135. request, command, index,
  136. (unsigned char *)buf, size, RAZER_USB_TIMEOUT);
  137. if (err < 0 || (size_t)err != size) {
  138. razer_error("razer-copperhead: "
  139. "USB read 0x%02X 0x%02X 0x%02X failed: %d\n",
  140. request, command, index, err);
  141. return -EIO;
  142. }
  143. return 0;
  144. }
  145. static int copperhead_read_fw_ver(struct copperhead_private *priv)
  146. {
  147. char buf[2];
  148. uint16_t ver;
  149. buf[0]=0; //TODO
  150. buf[1]=0;
  151. ver = buf[0];
  152. ver <<= 8;
  153. ver |= buf[1];
  154. return ver;
  155. }
  156. static int copperhead_do_commit(struct copperhead_private *priv)
  157. {
  158. union {
  159. struct copperhead_profcfg_cmd profcfg;
  160. uint8_t chunks[64 * 6];
  161. } _packed u;
  162. uint8_t *chunk;
  163. unsigned int i, j;
  164. int err;
  165. unsigned char value;
  166. BUILD_BUG_ON(sizeof(u) != 0x180);
  167. razer_event_spacing_enter(&priv->commit_spacing);
  168. /* Upload the profile config */
  169. for (i = 0; i < COPPERHEAD_NR_PROFILES; i++) {
  170. memset(&u, 0, sizeof(u));
  171. u.profcfg.packetlength = cpu_to_le16(sizeof(u.profcfg));
  172. u.profcfg.magic = COPPERHEAD_PROFCFG_MAGIC;
  173. u.profcfg.profilenr = cpu_to_le16(i + 1);
  174. u.profcfg.reply_profilenr = u.profcfg.profilenr;
  175. switch (priv->cur_dpimapping[i]->res[RAZER_DIM_0]) {
  176. default:
  177. case RAZER_MOUSE_RES_400DPI:
  178. u.profcfg.dpisel = 4;
  179. break;
  180. case RAZER_MOUSE_RES_800DPI:
  181. u.profcfg.dpisel = 3;
  182. break;
  183. case RAZER_MOUSE_RES_1600DPI:
  184. u.profcfg.dpisel = 2;
  185. break;
  186. case RAZER_MOUSE_RES_2000DPI:
  187. u.profcfg.dpisel = 1;
  188. break;
  189. }
  190. switch (priv->cur_freq[i]) {
  191. default:
  192. case RAZER_MOUSE_FREQ_125HZ:
  193. u.profcfg.freq = 3;
  194. break;
  195. case RAZER_MOUSE_FREQ_500HZ:
  196. u.profcfg.freq = 2;
  197. break;
  198. case RAZER_MOUSE_FREQ_1000HZ:
  199. u.profcfg.freq = 1;
  200. break;
  201. }
  202. err = razer_create_buttonmap(u.profcfg.buttonmap, sizeof(u.profcfg.buttonmap),
  203. priv->buttons[i].mapping,
  204. ARRAY_SIZE(priv->buttons[i].mapping), 46);
  205. if (err)
  206. goto out;
  207. u.profcfg.checksum = razer_xor16_checksum(&u.profcfg,
  208. sizeof(u.profcfg) - 2);
  209. /* The profile config is committed in 64byte chunks */
  210. chunk = &u.chunks[0];
  211. for (j = 0; j < 6; j++, chunk += 64) {
  212. err = copperhead_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
  213. j + 1, 0, chunk, 64);
  214. if (err)
  215. goto out;
  216. }
  217. /* Commit the profile */
  218. value = i + 1;
  219. copperhead_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
  220. 0x02, 3, &value, sizeof(value));
  221. /* Read back the result */
  222. BUILD_BUG_ON(0x156 + 6 != sizeof(u.profcfg));
  223. memset(&u, 0, sizeof(u));
  224. err = copperhead_usb_read(priv, LIBUSB_REQUEST_CLEAR_FEATURE,
  225. 0x01, 0, ((uint8_t *)&u.profcfg) + 6,
  226. sizeof(u.profcfg) - 6);
  227. if (err)
  228. goto out;
  229. if (razer_xor16_checksum(&u.profcfg, sizeof(u.profcfg))) {
  230. razer_error("hw_copperhead: Profile commit checksum mismatch\n");
  231. err = -EIO;
  232. goto out;
  233. }
  234. }
  235. /* Select the profile */
  236. value = priv->cur_profile->nr + 1;
  237. err = copperhead_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
  238. 0x02, 1, &value, sizeof(value));
  239. if (err)
  240. goto out;
  241. err = 0;
  242. out:
  243. razer_event_spacing_leave(&priv->commit_spacing);
  244. return err;
  245. }
  246. static int copperhead_read_config_from_hw(struct copperhead_private *priv)
  247. {
  248. struct copperhead_profcfg_cmd profcfg;
  249. unsigned int i;
  250. unsigned char value;
  251. int err;
  252. /* Read the current profile number. */
  253. err = copperhead_usb_read(priv, LIBUSB_REQUEST_CLEAR_FEATURE,
  254. 0x01, 0, &value, sizeof(value));
  255. if (err)
  256. return err;
  257. if (value < 1 || value > COPPERHEAD_NR_PROFILES) {
  258. razer_error("hw_copperhead: Got invalid profile number: %u\n",
  259. (unsigned int)value);
  260. value = 1;
  261. }
  262. priv->cur_profile = &priv->profiles[value - 1];
  263. /* Read the profiles config */
  264. for (i = 0; i < COPPERHEAD_NR_PROFILES; i++) {
  265. BUILD_BUG_ON(0x156 + 6 != sizeof(profcfg));
  266. /* Request profile config */
  267. value = i + 1;
  268. err = copperhead_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
  269. 0x02, 3, &value, sizeof(value));
  270. if (err)
  271. return err;
  272. /* Read profile config */
  273. memset(&profcfg, 0, sizeof(profcfg));
  274. err = copperhead_usb_read(priv, LIBUSB_REQUEST_CLEAR_FEATURE,
  275. 0x01, 0, ((uint8_t *)&profcfg) + 6,
  276. sizeof(profcfg) - 6);
  277. if (err)
  278. return err;
  279. if (razer_xor16_checksum(&profcfg, sizeof(profcfg))) {
  280. razer_error("hw_copperhead: Read profile data checksum mismatch\n");
  281. continue;
  282. }
  283. if (le16_to_cpu(profcfg.reply_profilenr) != i + 1) {
  284. razer_error("hw_copperhead: Got invalid profile nr in "
  285. "profile config: %u\n",
  286. (unsigned int)le16_to_cpu(profcfg.reply_profilenr));
  287. }
  288. switch (profcfg.dpisel) {
  289. case 4:
  290. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  291. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  292. RAZER_DIM_0, RAZER_MOUSE_RES_400DPI);
  293. break;
  294. case 3:
  295. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  296. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  297. RAZER_DIM_0, RAZER_MOUSE_RES_800DPI);
  298. break;
  299. case 2:
  300. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  301. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  302. RAZER_DIM_0, RAZER_MOUSE_RES_1600DPI);
  303. break;
  304. case 1:
  305. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  306. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  307. RAZER_DIM_0, RAZER_MOUSE_RES_2000DPI);
  308. break;
  309. default:
  310. razer_error("hw_copperhead: Got invalid DPI mapping selection\n");
  311. break;
  312. }
  313. if (!priv->cur_dpimapping[i]) {
  314. razer_error("hw_copperhead: Internal error: No dpimapping\n");
  315. return -ENODEV;
  316. }
  317. switch (profcfg.freq) {
  318. case 3:
  319. priv->cur_freq[i] = RAZER_MOUSE_FREQ_125HZ;
  320. break;
  321. case 2:
  322. priv->cur_freq[i] = RAZER_MOUSE_FREQ_500HZ;
  323. break;
  324. case 1:
  325. priv->cur_freq[i] = RAZER_MOUSE_FREQ_1000HZ;
  326. break;
  327. default:
  328. razer_error("hw_copperhead: Got invalid frequency selection\n");
  329. break;
  330. }
  331. err = razer_parse_buttonmap(profcfg.buttonmap, sizeof(profcfg.buttonmap),
  332. priv->buttons[i].mapping,
  333. ARRAY_SIZE(priv->buttons[i].mapping), 46);
  334. if (err)
  335. razer_error("hw_copperhead: Failed to parse button map\n");
  336. }
  337. return 0;
  338. }
  339. static int copperhead_get_fw_version(struct razer_mouse *m)
  340. {
  341. struct copperhead_private *priv = m->drv_data;
  342. return priv->fw_version;
  343. }
  344. static int copperhead_commit(struct razer_mouse *m, int force)
  345. {
  346. struct copperhead_private *priv = m->drv_data;
  347. int err = 0;
  348. if (!m->claim_count)
  349. return -EBUSY;
  350. if (priv->commit_pending || force) {
  351. err = copperhead_do_commit(priv);
  352. if (!err)
  353. priv->commit_pending = 0;
  354. }
  355. return err;
  356. }
  357. static struct razer_mouse_profile * copperhead_get_profiles(struct razer_mouse *m)
  358. {
  359. struct copperhead_private *priv = m->drv_data;
  360. return &priv->profiles[0];
  361. }
  362. static struct razer_mouse_profile * copperhead_get_active_profile(struct razer_mouse *m)
  363. {
  364. struct copperhead_private *priv = m->drv_data;
  365. return priv->cur_profile;
  366. }
  367. static int copperhead_set_active_profile(struct razer_mouse *m,
  368. struct razer_mouse_profile *p)
  369. {
  370. struct copperhead_private *priv = m->drv_data;
  371. if (!priv->m->claim_count)
  372. return -EBUSY;
  373. priv->cur_profile = p;
  374. priv->commit_pending = 1;
  375. return 0;
  376. }
  377. static int copperhead_supported_resolutions(struct razer_mouse *m,
  378. enum razer_mouse_res **res_list)
  379. {
  380. enum razer_mouse_res *list;
  381. const int count = 4;
  382. list = zalloc(sizeof(*list) * count);
  383. if (!list)
  384. return -ENOMEM;
  385. list[0] = RAZER_MOUSE_RES_400DPI;
  386. list[1] = RAZER_MOUSE_RES_800DPI;
  387. list[2] = RAZER_MOUSE_RES_1600DPI;
  388. list[3] = RAZER_MOUSE_RES_2000DPI;
  389. *res_list = list;
  390. return count;
  391. }
  392. static int copperhead_supported_freqs(struct razer_mouse *m,
  393. enum razer_mouse_freq **freq_list)
  394. {
  395. enum razer_mouse_freq *list;
  396. const int count = 3;
  397. list = zalloc(sizeof(*list) * count);
  398. if (!list)
  399. return -ENOMEM;
  400. list[0] = RAZER_MOUSE_FREQ_125HZ;
  401. list[1] = RAZER_MOUSE_FREQ_500HZ;
  402. list[2] = RAZER_MOUSE_FREQ_1000HZ;
  403. *freq_list = list;
  404. return count;
  405. }
  406. static enum razer_mouse_freq copperhead_get_freq(struct razer_mouse_profile *p)
  407. {
  408. struct copperhead_private *priv = p->mouse->drv_data;
  409. if (p->nr >= ARRAY_SIZE(priv->cur_freq))
  410. return -EINVAL;
  411. return priv->cur_freq[p->nr];
  412. }
  413. static int copperhead_set_freq(struct razer_mouse_profile *p,
  414. enum razer_mouse_freq freq)
  415. {
  416. struct copperhead_private *priv = p->mouse->drv_data;
  417. if (!priv->m->claim_count)
  418. return -EBUSY;
  419. if (p->nr >= ARRAY_SIZE(priv->cur_freq))
  420. return -EINVAL;
  421. priv->cur_freq[p->nr] = freq;
  422. priv->commit_pending = 1;
  423. return 0;
  424. }
  425. static int copperhead_supported_dpimappings(struct razer_mouse *m,
  426. struct razer_mouse_dpimapping **res_ptr)
  427. {
  428. struct copperhead_private *priv = m->drv_data;
  429. *res_ptr = &priv->dpimappings[0];
  430. return ARRAY_SIZE(priv->dpimappings);
  431. }
  432. static struct razer_mouse_dpimapping * copperhead_get_dpimapping(struct razer_mouse_profile *p,
  433. struct razer_axis *axis)
  434. {
  435. struct copperhead_private *priv = p->mouse->drv_data;
  436. if (p->nr >= ARRAY_SIZE(priv->cur_dpimapping))
  437. return NULL;
  438. return priv->cur_dpimapping[p->nr];
  439. }
  440. static int copperhead_set_dpimapping(struct razer_mouse_profile *p,
  441. struct razer_axis *axis,
  442. struct razer_mouse_dpimapping *d)
  443. {
  444. struct copperhead_private *priv = p->mouse->drv_data;
  445. if (!priv->m->claim_count)
  446. return -EBUSY;
  447. if (p->nr >= ARRAY_SIZE(priv->cur_dpimapping))
  448. return -EINVAL;
  449. priv->cur_dpimapping[p->nr] = d;
  450. priv->commit_pending = 1;
  451. return 0;
  452. }
  453. static int copperhead_supported_buttons(struct razer_mouse *m,
  454. struct razer_button **res_ptr)
  455. {
  456. *res_ptr = copperhead_physical_buttons;
  457. return ARRAY_SIZE(copperhead_physical_buttons);
  458. }
  459. static int copperhead_supported_button_functions(struct razer_mouse *m,
  460. struct razer_button_function **res_ptr)
  461. {
  462. *res_ptr = copperhead_button_functions;
  463. return ARRAY_SIZE(copperhead_button_functions);
  464. }
  465. static struct razer_button_function * copperhead_get_button_function(struct razer_mouse_profile *p,
  466. struct razer_button *b)
  467. {
  468. struct copperhead_private *priv = p->mouse->drv_data;
  469. struct copperhead_buttons *buttons;
  470. if (p->nr > ARRAY_SIZE(priv->buttons))
  471. return NULL;
  472. buttons = &priv->buttons[p->nr];
  473. return razer_get_buttonfunction_by_button(
  474. buttons->mapping, ARRAY_SIZE(buttons->mapping),
  475. copperhead_button_functions, ARRAY_SIZE(copperhead_button_functions),
  476. b);
  477. }
  478. static int copperhead_set_button_function(struct razer_mouse_profile *p,
  479. struct razer_button *b,
  480. struct razer_button_function *f)
  481. {
  482. struct copperhead_private *priv = p->mouse->drv_data;
  483. struct copperhead_buttons *buttons;
  484. struct razer_buttonmapping *mapping;
  485. if (!priv->m->claim_count)
  486. return -EBUSY;
  487. if (p->nr > ARRAY_SIZE(priv->buttons))
  488. return -EINVAL;
  489. buttons = &priv->buttons[p->nr];
  490. mapping = razer_get_buttonmapping_by_physid(
  491. buttons->mapping, ARRAY_SIZE(buttons->mapping),
  492. b->id);
  493. if (!mapping)
  494. return -ENODEV;
  495. mapping->logical = f->id;
  496. priv->commit_pending = 1;
  497. return 0;
  498. }
  499. int razer_copperhead_init(struct razer_mouse *m,
  500. struct libusb_device *usbdev)
  501. {
  502. struct copperhead_private *priv;
  503. unsigned int i;
  504. int err;
  505. BUILD_BUG_ON(sizeof(struct copperhead_profcfg_cmd) != 0x15C);
  506. priv = zalloc(sizeof(struct copperhead_private));
  507. if (!priv)
  508. return -ENOMEM;
  509. priv->m = m;
  510. m->drv_data = priv;
  511. /* We need to wait some time between commits */
  512. razer_event_spacing_init(&priv->commit_spacing, 250);
  513. err = razer_usb_add_used_interface(m->usb_ctx, 0, 0);
  514. err |= razer_usb_add_used_interface(m->usb_ctx, 1, 0);
  515. if (err) {
  516. err = -EIO;
  517. goto err_free;
  518. }
  519. priv->dpimappings[0].nr = 0;
  520. priv->dpimappings[0].res[RAZER_DIM_0] = RAZER_MOUSE_RES_400DPI;
  521. priv->dpimappings[0].dimension_mask = (1 << RAZER_DIM_0);
  522. priv->dpimappings[0].mouse = m;
  523. priv->dpimappings[1].nr = 1;
  524. priv->dpimappings[1].res[RAZER_DIM_0] = RAZER_MOUSE_RES_800DPI;
  525. priv->dpimappings[1].dimension_mask = (1 << RAZER_DIM_0);
  526. priv->dpimappings[1].mouse = m;
  527. priv->dpimappings[2].nr = 2;
  528. priv->dpimappings[2].res[RAZER_DIM_0] = RAZER_MOUSE_RES_1600DPI;
  529. priv->dpimappings[2].dimension_mask = (1 << RAZER_DIM_0);
  530. priv->dpimappings[2].mouse = m;
  531. priv->dpimappings[3].nr = 3;
  532. priv->dpimappings[3].res[RAZER_DIM_0] = RAZER_MOUSE_RES_2000DPI;
  533. priv->dpimappings[3].dimension_mask = (1 << RAZER_DIM_0);
  534. priv->dpimappings[3].mouse = m;
  535. for (i = 0; i < COPPERHEAD_NR_PROFILES; i++) {
  536. priv->profiles[i].nr = i;
  537. priv->profiles[i].get_freq = copperhead_get_freq;
  538. priv->profiles[i].set_freq = copperhead_set_freq;
  539. priv->profiles[i].get_dpimapping = copperhead_get_dpimapping;
  540. priv->profiles[i].set_dpimapping = copperhead_set_dpimapping;
  541. priv->profiles[i].get_button_function = copperhead_get_button_function;
  542. priv->profiles[i].set_button_function = copperhead_set_button_function;
  543. priv->profiles[i].mouse = m;
  544. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  545. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  546. RAZER_DIM_0, RAZER_MOUSE_RES_400DPI);
  547. priv->cur_freq[i] = RAZER_MOUSE_FREQ_125HZ;
  548. }
  549. err = m->claim(m);
  550. if (err) {
  551. razer_error("hw_copperhead: "
  552. "Failed to initially claim the device\n");
  553. goto err_free;
  554. }
  555. err = copperhead_read_fw_ver(priv);
  556. if (err) {
  557. razer_error("hw_copperhead: Failed to fetch firmware version number\n");
  558. goto err_release;
  559. }
  560. err = copperhead_read_config_from_hw(priv);
  561. if (err) {
  562. razer_error("hw_copperhead: Failed to read config from hardware\n");
  563. goto err_release;
  564. }
  565. m->type = RAZER_MOUSETYPE_COPPERHEAD;
  566. razer_generic_usb_gen_idstr(usbdev, NULL, "Copperhead", 1,
  567. NULL, m->idstr);
  568. m->get_fw_version = copperhead_get_fw_version;
  569. m->commit = copperhead_commit;
  570. m->nr_profiles = COPPERHEAD_NR_PROFILES;
  571. m->get_profiles = copperhead_get_profiles;
  572. m->get_active_profile = copperhead_get_active_profile;
  573. m->set_active_profile = copperhead_set_active_profile;
  574. m->supported_resolutions = copperhead_supported_resolutions;
  575. m->supported_freqs = copperhead_supported_freqs;
  576. m->supported_dpimappings = copperhead_supported_dpimappings;
  577. m->supported_buttons = copperhead_supported_buttons;
  578. m->supported_button_functions = copperhead_supported_button_functions;
  579. err = copperhead_do_commit(priv);
  580. if (err) {
  581. razer_error("hw_copperhead: Failed to commit initial config\n");
  582. goto err_release;
  583. }
  584. m->release(m);
  585. return 0;
  586. err_release:
  587. m->release(m);
  588. err_free:
  589. free(priv);
  590. return err;
  591. }
  592. void razer_copperhead_release(struct razer_mouse *m)
  593. {
  594. struct copperhead_private *priv = m->drv_data;
  595. free(priv);
  596. }