hw_copperhead.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  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-2011 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\n");
  259. return -EIO;
  260. }
  261. priv->cur_profile = &priv->profiles[value - 1];
  262. /* Read the profiles config */
  263. for (i = 0; i < COPPERHEAD_NR_PROFILES; i++) {
  264. BUILD_BUG_ON(0x156 + 6 != sizeof(profcfg));
  265. /* Request profile config */
  266. value = i + 1;
  267. err = copperhead_usb_write(priv, LIBUSB_REQUEST_SET_CONFIGURATION,
  268. 0x02, 3, &value, sizeof(value));
  269. if (err)
  270. return err;
  271. /* Read profile config */
  272. memset(&profcfg, 0, sizeof(profcfg));
  273. err = copperhead_usb_read(priv, LIBUSB_REQUEST_CLEAR_FEATURE,
  274. 0x01, 0, ((uint8_t *)&profcfg) + 6,
  275. sizeof(profcfg) - 6);
  276. if (err)
  277. return err;
  278. if (razer_xor16_checksum(&profcfg, sizeof(profcfg))) {
  279. razer_error("hw_copperhead: Read profile data checksum mismatch\n");
  280. return -EIO;
  281. }
  282. if (le16_to_cpu(profcfg.reply_profilenr) != i + 1) {
  283. razer_error("hw_copperhead: Got invalid profile nr in profile config\n");
  284. return -EIO;
  285. }
  286. switch (profcfg.dpisel) {
  287. case 4:
  288. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  289. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  290. RAZER_DIM_0, RAZER_MOUSE_RES_400DPI);
  291. break;
  292. case 3:
  293. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  294. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  295. RAZER_DIM_0, RAZER_MOUSE_RES_800DPI);
  296. break;
  297. case 2:
  298. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  299. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  300. RAZER_DIM_0, RAZER_MOUSE_RES_1600DPI);
  301. break;
  302. case 1:
  303. priv->cur_dpimapping[i] = razer_mouse_get_dpimapping_by_res(
  304. priv->dpimappings, ARRAY_SIZE(priv->dpimappings),
  305. RAZER_DIM_0, RAZER_MOUSE_RES_2000DPI);
  306. break;
  307. default:
  308. razer_error("hw_copperhead: Got invalid DPI mapping selection\n");
  309. return -EIO;
  310. }
  311. if (!priv->cur_dpimapping[i]) {
  312. razer_error("hw_copperhead: Internal error: Did not find dpimapping\n");
  313. return -ENODEV;
  314. }
  315. switch (profcfg.freq) {
  316. case 3:
  317. priv->cur_freq[i] = RAZER_MOUSE_FREQ_125HZ;
  318. break;
  319. case 2:
  320. priv->cur_freq[i] = RAZER_MOUSE_FREQ_500HZ;
  321. break;
  322. case 1:
  323. priv->cur_freq[i] = RAZER_MOUSE_FREQ_1000HZ;
  324. break;
  325. default:
  326. razer_error("hw_copperhead: Got invalid frequency selection\n");
  327. return -EIO;
  328. }
  329. err = razer_parse_buttonmap(profcfg.buttonmap, sizeof(profcfg.buttonmap),
  330. priv->buttons[i].mapping,
  331. ARRAY_SIZE(priv->buttons[i].mapping), 46);
  332. if (err)
  333. return err;
  334. }
  335. return 0;
  336. }
  337. static int copperhead_get_fw_version(struct razer_mouse *m)
  338. {
  339. struct copperhead_private *priv = m->drv_data;
  340. return priv->fw_version;
  341. }
  342. static int copperhead_commit(struct razer_mouse *m, int force)
  343. {
  344. struct copperhead_private *priv = m->drv_data;
  345. int err = 0;
  346. if (!m->claim_count)
  347. return -EBUSY;
  348. if (priv->commit_pending || force) {
  349. err = copperhead_do_commit(priv);
  350. if (!err)
  351. priv->commit_pending = 0;
  352. }
  353. return err;
  354. }
  355. static struct razer_mouse_profile * copperhead_get_profiles(struct razer_mouse *m)
  356. {
  357. struct copperhead_private *priv = m->drv_data;
  358. return &priv->profiles[0];
  359. }
  360. static struct razer_mouse_profile * copperhead_get_active_profile(struct razer_mouse *m)
  361. {
  362. struct copperhead_private *priv = m->drv_data;
  363. return priv->cur_profile;
  364. }
  365. static int copperhead_set_active_profile(struct razer_mouse *m,
  366. struct razer_mouse_profile *p)
  367. {
  368. struct copperhead_private *priv = m->drv_data;
  369. if (!priv->m->claim_count)
  370. return -EBUSY;
  371. priv->cur_profile = p;
  372. priv->commit_pending = 1;
  373. return 0;
  374. }
  375. static int copperhead_supported_resolutions(struct razer_mouse *m,
  376. enum razer_mouse_res **res_list)
  377. {
  378. enum razer_mouse_res *list;
  379. const int count = 4;
  380. list = zalloc(sizeof(*list) * count);
  381. if (!list)
  382. return -ENOMEM;
  383. list[0] = RAZER_MOUSE_RES_400DPI;
  384. list[1] = RAZER_MOUSE_RES_800DPI;
  385. list[2] = RAZER_MOUSE_RES_1600DPI;
  386. list[3] = RAZER_MOUSE_RES_2000DPI;
  387. *res_list = list;
  388. return count;
  389. }
  390. static int copperhead_supported_freqs(struct razer_mouse *m,
  391. enum razer_mouse_freq **freq_list)
  392. {
  393. enum razer_mouse_freq *list;
  394. const int count = 3;
  395. list = zalloc(sizeof(*list) * count);
  396. if (!list)
  397. return -ENOMEM;
  398. list[0] = RAZER_MOUSE_FREQ_125HZ;
  399. list[1] = RAZER_MOUSE_FREQ_500HZ;
  400. list[2] = RAZER_MOUSE_FREQ_1000HZ;
  401. *freq_list = list;
  402. return count;
  403. }
  404. static enum razer_mouse_freq copperhead_get_freq(struct razer_mouse_profile *p)
  405. {
  406. struct copperhead_private *priv = p->mouse->drv_data;
  407. if (p->nr >= ARRAY_SIZE(priv->cur_freq))
  408. return -EINVAL;
  409. return priv->cur_freq[p->nr];
  410. }
  411. static int copperhead_set_freq(struct razer_mouse_profile *p,
  412. enum razer_mouse_freq freq)
  413. {
  414. struct copperhead_private *priv = p->mouse->drv_data;
  415. if (!priv->m->claim_count)
  416. return -EBUSY;
  417. if (p->nr >= ARRAY_SIZE(priv->cur_freq))
  418. return -EINVAL;
  419. priv->cur_freq[p->nr] = freq;
  420. priv->commit_pending = 1;
  421. return 0;
  422. }
  423. static int copperhead_supported_dpimappings(struct razer_mouse *m,
  424. struct razer_mouse_dpimapping **res_ptr)
  425. {
  426. struct copperhead_private *priv = m->drv_data;
  427. *res_ptr = &priv->dpimappings[0];
  428. return ARRAY_SIZE(priv->dpimappings);
  429. }
  430. static struct razer_mouse_dpimapping * copperhead_get_dpimapping(struct razer_mouse_profile *p,
  431. struct razer_axis *axis)
  432. {
  433. struct copperhead_private *priv = p->mouse->drv_data;
  434. if (p->nr >= ARRAY_SIZE(priv->cur_dpimapping))
  435. return NULL;
  436. return priv->cur_dpimapping[p->nr];
  437. }
  438. static int copperhead_set_dpimapping(struct razer_mouse_profile *p,
  439. struct razer_axis *axis,
  440. struct razer_mouse_dpimapping *d)
  441. {
  442. struct copperhead_private *priv = p->mouse->drv_data;
  443. if (!priv->m->claim_count)
  444. return -EBUSY;
  445. if (p->nr >= ARRAY_SIZE(priv->cur_dpimapping))
  446. return -EINVAL;
  447. priv->cur_dpimapping[p->nr] = d;
  448. priv->commit_pending = 1;
  449. return 0;
  450. }
  451. static int copperhead_supported_buttons(struct razer_mouse *m,
  452. struct razer_button **res_ptr)
  453. {
  454. *res_ptr = copperhead_physical_buttons;
  455. return ARRAY_SIZE(copperhead_physical_buttons);
  456. }
  457. static int copperhead_supported_button_functions(struct razer_mouse *m,
  458. struct razer_button_function **res_ptr)
  459. {
  460. *res_ptr = copperhead_button_functions;
  461. return ARRAY_SIZE(copperhead_button_functions);
  462. }
  463. static struct razer_button_function * copperhead_get_button_function(struct razer_mouse_profile *p,
  464. struct razer_button *b)
  465. {
  466. struct copperhead_private *priv = p->mouse->drv_data;
  467. struct copperhead_buttons *buttons;
  468. if (p->nr > ARRAY_SIZE(priv->buttons))
  469. return NULL;
  470. buttons = &priv->buttons[p->nr];
  471. return razer_get_buttonfunction_by_button(
  472. buttons->mapping, ARRAY_SIZE(buttons->mapping),
  473. copperhead_button_functions, ARRAY_SIZE(copperhead_button_functions),
  474. b);
  475. }
  476. static int copperhead_set_button_function(struct razer_mouse_profile *p,
  477. struct razer_button *b,
  478. struct razer_button_function *f)
  479. {
  480. struct copperhead_private *priv = p->mouse->drv_data;
  481. struct copperhead_buttons *buttons;
  482. struct razer_buttonmapping *mapping;
  483. if (!priv->m->claim_count)
  484. return -EBUSY;
  485. if (p->nr > ARRAY_SIZE(priv->buttons))
  486. return -EINVAL;
  487. buttons = &priv->buttons[p->nr];
  488. mapping = razer_get_buttonmapping_by_physid(
  489. buttons->mapping, ARRAY_SIZE(buttons->mapping),
  490. b->id);
  491. if (!mapping)
  492. return -ENODEV;
  493. mapping->logical = f->id;
  494. priv->commit_pending = 1;
  495. return 0;
  496. }
  497. int razer_copperhead_init(struct razer_mouse *m,
  498. struct libusb_device *usbdev)
  499. {
  500. struct copperhead_private *priv;
  501. unsigned int i;
  502. int err;
  503. BUILD_BUG_ON(sizeof(struct copperhead_profcfg_cmd) != 0x15C);
  504. priv = zalloc(sizeof(struct copperhead_private));
  505. if (!priv)
  506. return -ENOMEM;
  507. priv->m = m;
  508. m->drv_data = priv;
  509. /* We need to wait some time between commits */
  510. razer_event_spacing_init(&priv->commit_spacing, 250);
  511. err = razer_usb_add_used_interface(m->usb_ctx, 0, 0);
  512. err |= razer_usb_add_used_interface(m->usb_ctx, 1, 0);
  513. if (err) {
  514. err = -EIO;
  515. goto err_free;
  516. }
  517. priv->dpimappings[0].nr = 0;
  518. priv->dpimappings[0].res[RAZER_DIM_0] = RAZER_MOUSE_RES_400DPI;
  519. priv->dpimappings[0].dimension_mask = (1 << RAZER_DIM_0);
  520. priv->dpimappings[0].mouse = m;
  521. priv->dpimappings[1].nr = 1;
  522. priv->dpimappings[1].res[RAZER_DIM_0] = RAZER_MOUSE_RES_800DPI;
  523. priv->dpimappings[1].dimension_mask = (1 << RAZER_DIM_0);
  524. priv->dpimappings[1].mouse = m;
  525. priv->dpimappings[2].nr = 2;
  526. priv->dpimappings[2].res[RAZER_DIM_0] = RAZER_MOUSE_RES_1600DPI;
  527. priv->dpimappings[2].dimension_mask = (1 << RAZER_DIM_0);
  528. priv->dpimappings[2].mouse = m;
  529. priv->dpimappings[3].nr = 3;
  530. priv->dpimappings[3].res[RAZER_DIM_0] = RAZER_MOUSE_RES_2000DPI;
  531. priv->dpimappings[3].dimension_mask = (1 << RAZER_DIM_0);
  532. priv->dpimappings[3].mouse = m;
  533. for (i = 0; i < COPPERHEAD_NR_PROFILES; i++) {
  534. priv->profiles[i].nr = i;
  535. priv->profiles[i].get_freq = copperhead_get_freq;
  536. priv->profiles[i].set_freq = copperhead_set_freq;
  537. priv->profiles[i].get_dpimapping = copperhead_get_dpimapping;
  538. priv->profiles[i].set_dpimapping = copperhead_set_dpimapping;
  539. priv->profiles[i].get_button_function = copperhead_get_button_function;
  540. priv->profiles[i].set_button_function = copperhead_set_button_function;
  541. priv->profiles[i].mouse = m;
  542. }
  543. err = m->claim(m);
  544. if (err) {
  545. razer_error("hw_copperhead: "
  546. "Failed to initially claim the device\n");
  547. goto err_free;
  548. }
  549. err = copperhead_read_fw_ver(priv);
  550. if (err) {
  551. razer_error("hw_copperhead: Failed to fetch firmware version number\n");
  552. goto err_release;
  553. }
  554. err = copperhead_read_config_from_hw(priv);
  555. if (err) {
  556. razer_error("hw_copperhead: Failed to read config from hardware\n");
  557. goto err_release;
  558. }
  559. m->type = RAZER_MOUSETYPE_COPPERHEAD;
  560. razer_generic_usb_gen_idstr(usbdev, NULL, "Copperhead", 1,
  561. NULL, m->idstr);
  562. m->get_fw_version = copperhead_get_fw_version;
  563. m->commit = copperhead_commit;
  564. m->nr_profiles = COPPERHEAD_NR_PROFILES;
  565. m->get_profiles = copperhead_get_profiles;
  566. m->get_active_profile = copperhead_get_active_profile;
  567. m->set_active_profile = copperhead_set_active_profile;
  568. m->supported_resolutions = copperhead_supported_resolutions;
  569. m->supported_freqs = copperhead_supported_freqs;
  570. m->supported_dpimappings = copperhead_supported_dpimappings;
  571. m->supported_buttons = copperhead_supported_buttons;
  572. m->supported_button_functions = copperhead_supported_button_functions;
  573. err = copperhead_do_commit(priv);
  574. if (err) {
  575. razer_error("hw_copperhead: Failed to commit initial config\n");
  576. goto err_release;
  577. }
  578. m->release(m);
  579. return 0;
  580. err_release:
  581. m->release(m);
  582. err_free:
  583. free(priv);
  584. return err;
  585. }
  586. void razer_copperhead_release(struct razer_mouse *m)
  587. {
  588. struct copperhead_private *priv = m->drv_data;
  589. free(priv);
  590. }