hid-corsair.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. /*
  2. * HID driver for Corsair devices
  3. *
  4. * Supported devices:
  5. * - Vengeance K90 Keyboard
  6. * - Scimitar PRO RGB Gaming Mouse
  7. *
  8. * Copyright (c) 2015 Clement Vuchener
  9. * Copyright (c) 2017 Oscar Campos
  10. */
  11. /*
  12. * This program is free software; you can redistribute it and/or modify it
  13. * under the terms of the GNU General Public License as published by the Free
  14. * Software Foundation; either version 2 of the License, or (at your option)
  15. * any later version.
  16. */
  17. #include <linux/hid.h>
  18. #include <linux/module.h>
  19. #include <linux/usb.h>
  20. #include <linux/leds.h>
  21. #include "hid-ids.h"
  22. #define CORSAIR_USE_K90_MACRO (1<<0)
  23. #define CORSAIR_USE_K90_BACKLIGHT (1<<1)
  24. struct k90_led {
  25. struct led_classdev cdev;
  26. int brightness;
  27. struct work_struct work;
  28. bool removed;
  29. };
  30. struct k90_drvdata {
  31. struct k90_led record_led;
  32. };
  33. struct corsair_drvdata {
  34. unsigned long quirks;
  35. struct k90_drvdata *k90;
  36. struct k90_led *backlight;
  37. };
  38. #define K90_GKEY_COUNT 18
  39. static int corsair_usage_to_gkey(unsigned int usage)
  40. {
  41. /* G1 (0xd0) to G16 (0xdf) */
  42. if (usage >= 0xd0 && usage <= 0xdf)
  43. return usage - 0xd0 + 1;
  44. /* G17 (0xe8) to G18 (0xe9) */
  45. if (usage >= 0xe8 && usage <= 0xe9)
  46. return usage - 0xe8 + 17;
  47. return 0;
  48. }
  49. static unsigned short corsair_gkey_map[K90_GKEY_COUNT] = {
  50. BTN_TRIGGER_HAPPY1,
  51. BTN_TRIGGER_HAPPY2,
  52. BTN_TRIGGER_HAPPY3,
  53. BTN_TRIGGER_HAPPY4,
  54. BTN_TRIGGER_HAPPY5,
  55. BTN_TRIGGER_HAPPY6,
  56. BTN_TRIGGER_HAPPY7,
  57. BTN_TRIGGER_HAPPY8,
  58. BTN_TRIGGER_HAPPY9,
  59. BTN_TRIGGER_HAPPY10,
  60. BTN_TRIGGER_HAPPY11,
  61. BTN_TRIGGER_HAPPY12,
  62. BTN_TRIGGER_HAPPY13,
  63. BTN_TRIGGER_HAPPY14,
  64. BTN_TRIGGER_HAPPY15,
  65. BTN_TRIGGER_HAPPY16,
  66. BTN_TRIGGER_HAPPY17,
  67. BTN_TRIGGER_HAPPY18,
  68. };
  69. module_param_array_named(gkey_codes, corsair_gkey_map, ushort, NULL, S_IRUGO);
  70. MODULE_PARM_DESC(gkey_codes, "Key codes for the G-keys");
  71. static unsigned short corsair_record_keycodes[2] = {
  72. BTN_TRIGGER_HAPPY19,
  73. BTN_TRIGGER_HAPPY20
  74. };
  75. module_param_array_named(recordkey_codes, corsair_record_keycodes, ushort,
  76. NULL, S_IRUGO);
  77. MODULE_PARM_DESC(recordkey_codes, "Key codes for the MR (start and stop record) button");
  78. static unsigned short corsair_profile_keycodes[3] = {
  79. BTN_TRIGGER_HAPPY21,
  80. BTN_TRIGGER_HAPPY22,
  81. BTN_TRIGGER_HAPPY23
  82. };
  83. module_param_array_named(profilekey_codes, corsair_profile_keycodes, ushort,
  84. NULL, S_IRUGO);
  85. MODULE_PARM_DESC(profilekey_codes, "Key codes for the profile buttons");
  86. #define CORSAIR_USAGE_SPECIAL_MIN 0xf0
  87. #define CORSAIR_USAGE_SPECIAL_MAX 0xff
  88. #define CORSAIR_USAGE_MACRO_RECORD_START 0xf6
  89. #define CORSAIR_USAGE_MACRO_RECORD_STOP 0xf7
  90. #define CORSAIR_USAGE_PROFILE 0xf1
  91. #define CORSAIR_USAGE_M1 0xf1
  92. #define CORSAIR_USAGE_M2 0xf2
  93. #define CORSAIR_USAGE_M3 0xf3
  94. #define CORSAIR_USAGE_PROFILE_MAX 0xf3
  95. #define CORSAIR_USAGE_META_OFF 0xf4
  96. #define CORSAIR_USAGE_META_ON 0xf5
  97. #define CORSAIR_USAGE_LIGHT 0xfa
  98. #define CORSAIR_USAGE_LIGHT_OFF 0xfa
  99. #define CORSAIR_USAGE_LIGHT_DIM 0xfb
  100. #define CORSAIR_USAGE_LIGHT_MEDIUM 0xfc
  101. #define CORSAIR_USAGE_LIGHT_BRIGHT 0xfd
  102. #define CORSAIR_USAGE_LIGHT_MAX 0xfd
  103. /* USB control protocol */
  104. #define K90_REQUEST_BRIGHTNESS 49
  105. #define K90_REQUEST_MACRO_MODE 2
  106. #define K90_REQUEST_STATUS 4
  107. #define K90_REQUEST_GET_MODE 5
  108. #define K90_REQUEST_PROFILE 20
  109. #define K90_MACRO_MODE_SW 0x0030
  110. #define K90_MACRO_MODE_HW 0x0001
  111. #define K90_MACRO_LED_ON 0x0020
  112. #define K90_MACRO_LED_OFF 0x0040
  113. /*
  114. * LED class devices
  115. */
  116. #define K90_BACKLIGHT_LED_SUFFIX "::backlight"
  117. #define K90_RECORD_LED_SUFFIX "::record"
  118. static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev)
  119. {
  120. int ret;
  121. struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
  122. struct device *dev = led->cdev.dev->parent;
  123. struct usb_interface *usbif = to_usb_interface(dev->parent);
  124. struct usb_device *usbdev = interface_to_usbdev(usbif);
  125. int brightness;
  126. char *data;
  127. data = kmalloc(8, GFP_KERNEL);
  128. if (!data)
  129. return -ENOMEM;
  130. ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
  131. K90_REQUEST_STATUS,
  132. USB_DIR_IN | USB_TYPE_VENDOR |
  133. USB_RECIP_DEVICE, 0, 0, data, 8,
  134. USB_CTRL_SET_TIMEOUT);
  135. if (ret < 5) {
  136. dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
  137. ret);
  138. ret = -EIO;
  139. goto out;
  140. }
  141. brightness = data[4];
  142. if (brightness < 0 || brightness > 3) {
  143. dev_warn(dev,
  144. "Read invalid backlight brightness: %02hhx.\n",
  145. data[4]);
  146. ret = -EIO;
  147. goto out;
  148. }
  149. ret = brightness;
  150. out:
  151. kfree(data);
  152. return ret;
  153. }
  154. static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev)
  155. {
  156. struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
  157. return led->brightness;
  158. }
  159. static void k90_brightness_set(struct led_classdev *led_cdev,
  160. enum led_brightness brightness)
  161. {
  162. struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
  163. led->brightness = brightness;
  164. schedule_work(&led->work);
  165. }
  166. static void k90_backlight_work(struct work_struct *work)
  167. {
  168. int ret;
  169. struct k90_led *led = container_of(work, struct k90_led, work);
  170. struct device *dev;
  171. struct usb_interface *usbif;
  172. struct usb_device *usbdev;
  173. if (led->removed)
  174. return;
  175. dev = led->cdev.dev->parent;
  176. usbif = to_usb_interface(dev->parent);
  177. usbdev = interface_to_usbdev(usbif);
  178. ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
  179. K90_REQUEST_BRIGHTNESS,
  180. USB_DIR_OUT | USB_TYPE_VENDOR |
  181. USB_RECIP_DEVICE, led->brightness, 0,
  182. NULL, 0, USB_CTRL_SET_TIMEOUT);
  183. if (ret != 0)
  184. dev_warn(dev, "Failed to set backlight brightness (error: %d).\n",
  185. ret);
  186. }
  187. static void k90_record_led_work(struct work_struct *work)
  188. {
  189. int ret;
  190. struct k90_led *led = container_of(work, struct k90_led, work);
  191. struct device *dev;
  192. struct usb_interface *usbif;
  193. struct usb_device *usbdev;
  194. int value;
  195. if (led->removed)
  196. return;
  197. dev = led->cdev.dev->parent;
  198. usbif = to_usb_interface(dev->parent);
  199. usbdev = interface_to_usbdev(usbif);
  200. if (led->brightness > 0)
  201. value = K90_MACRO_LED_ON;
  202. else
  203. value = K90_MACRO_LED_OFF;
  204. ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
  205. K90_REQUEST_MACRO_MODE,
  206. USB_DIR_OUT | USB_TYPE_VENDOR |
  207. USB_RECIP_DEVICE, value, 0, NULL, 0,
  208. USB_CTRL_SET_TIMEOUT);
  209. if (ret != 0)
  210. dev_warn(dev, "Failed to set record LED state (error: %d).\n",
  211. ret);
  212. }
  213. /*
  214. * Keyboard attributes
  215. */
  216. static ssize_t k90_show_macro_mode(struct device *dev,
  217. struct device_attribute *attr, char *buf)
  218. {
  219. int ret;
  220. struct usb_interface *usbif = to_usb_interface(dev->parent);
  221. struct usb_device *usbdev = interface_to_usbdev(usbif);
  222. const char *macro_mode;
  223. char *data;
  224. data = kmalloc(2, GFP_KERNEL);
  225. if (!data)
  226. return -ENOMEM;
  227. ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
  228. K90_REQUEST_GET_MODE,
  229. USB_DIR_IN | USB_TYPE_VENDOR |
  230. USB_RECIP_DEVICE, 0, 0, data, 2,
  231. USB_CTRL_SET_TIMEOUT);
  232. if (ret < 1) {
  233. dev_warn(dev, "Failed to get K90 initial mode (error %d).\n",
  234. ret);
  235. ret = -EIO;
  236. goto out;
  237. }
  238. switch (data[0]) {
  239. case K90_MACRO_MODE_HW:
  240. macro_mode = "HW";
  241. break;
  242. case K90_MACRO_MODE_SW:
  243. macro_mode = "SW";
  244. break;
  245. default:
  246. dev_warn(dev, "K90 in unknown mode: %02hhx.\n",
  247. data[0]);
  248. ret = -EIO;
  249. goto out;
  250. }
  251. ret = snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
  252. out:
  253. kfree(data);
  254. return ret;
  255. }
  256. static ssize_t k90_store_macro_mode(struct device *dev,
  257. struct device_attribute *attr,
  258. const char *buf, size_t count)
  259. {
  260. int ret;
  261. struct usb_interface *usbif = to_usb_interface(dev->parent);
  262. struct usb_device *usbdev = interface_to_usbdev(usbif);
  263. __u16 value;
  264. if (strncmp(buf, "SW", 2) == 0)
  265. value = K90_MACRO_MODE_SW;
  266. else if (strncmp(buf, "HW", 2) == 0)
  267. value = K90_MACRO_MODE_HW;
  268. else
  269. return -EINVAL;
  270. ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
  271. K90_REQUEST_MACRO_MODE,
  272. USB_DIR_OUT | USB_TYPE_VENDOR |
  273. USB_RECIP_DEVICE, value, 0, NULL, 0,
  274. USB_CTRL_SET_TIMEOUT);
  275. if (ret != 0) {
  276. dev_warn(dev, "Failed to set macro mode.\n");
  277. return ret;
  278. }
  279. return count;
  280. }
  281. static ssize_t k90_show_current_profile(struct device *dev,
  282. struct device_attribute *attr,
  283. char *buf)
  284. {
  285. int ret;
  286. struct usb_interface *usbif = to_usb_interface(dev->parent);
  287. struct usb_device *usbdev = interface_to_usbdev(usbif);
  288. int current_profile;
  289. char *data;
  290. data = kmalloc(8, GFP_KERNEL);
  291. if (!data)
  292. return -ENOMEM;
  293. ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
  294. K90_REQUEST_STATUS,
  295. USB_DIR_IN | USB_TYPE_VENDOR |
  296. USB_RECIP_DEVICE, 0, 0, data, 8,
  297. USB_CTRL_SET_TIMEOUT);
  298. if (ret < 8) {
  299. dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
  300. ret);
  301. ret = -EIO;
  302. goto out;
  303. }
  304. current_profile = data[7];
  305. if (current_profile < 1 || current_profile > 3) {
  306. dev_warn(dev, "Read invalid current profile: %02hhx.\n",
  307. data[7]);
  308. ret = -EIO;
  309. goto out;
  310. }
  311. ret = snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
  312. out:
  313. kfree(data);
  314. return ret;
  315. }
  316. static ssize_t k90_store_current_profile(struct device *dev,
  317. struct device_attribute *attr,
  318. const char *buf, size_t count)
  319. {
  320. int ret;
  321. struct usb_interface *usbif = to_usb_interface(dev->parent);
  322. struct usb_device *usbdev = interface_to_usbdev(usbif);
  323. int profile;
  324. if (kstrtoint(buf, 10, &profile))
  325. return -EINVAL;
  326. if (profile < 1 || profile > 3)
  327. return -EINVAL;
  328. ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
  329. K90_REQUEST_PROFILE,
  330. USB_DIR_OUT | USB_TYPE_VENDOR |
  331. USB_RECIP_DEVICE, profile, 0, NULL, 0,
  332. USB_CTRL_SET_TIMEOUT);
  333. if (ret != 0) {
  334. dev_warn(dev, "Failed to change current profile (error %d).\n",
  335. ret);
  336. return ret;
  337. }
  338. return count;
  339. }
  340. static DEVICE_ATTR(macro_mode, 0644, k90_show_macro_mode, k90_store_macro_mode);
  341. static DEVICE_ATTR(current_profile, 0644, k90_show_current_profile,
  342. k90_store_current_profile);
  343. static struct attribute *k90_attrs[] = {
  344. &dev_attr_macro_mode.attr,
  345. &dev_attr_current_profile.attr,
  346. NULL
  347. };
  348. static const struct attribute_group k90_attr_group = {
  349. .attrs = k90_attrs,
  350. };
  351. /*
  352. * Driver functions
  353. */
  354. static int k90_init_backlight(struct hid_device *dev)
  355. {
  356. int ret;
  357. struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
  358. size_t name_sz;
  359. char *name;
  360. drvdata->backlight = kzalloc(sizeof(struct k90_led), GFP_KERNEL);
  361. if (!drvdata->backlight) {
  362. ret = -ENOMEM;
  363. goto fail_backlight_alloc;
  364. }
  365. name_sz =
  366. strlen(dev_name(&dev->dev)) + sizeof(K90_BACKLIGHT_LED_SUFFIX);
  367. name = kzalloc(name_sz, GFP_KERNEL);
  368. if (!name) {
  369. ret = -ENOMEM;
  370. goto fail_name_alloc;
  371. }
  372. snprintf(name, name_sz, "%s" K90_BACKLIGHT_LED_SUFFIX,
  373. dev_name(&dev->dev));
  374. drvdata->backlight->removed = false;
  375. drvdata->backlight->cdev.name = name;
  376. drvdata->backlight->cdev.max_brightness = 3;
  377. drvdata->backlight->cdev.brightness_set = k90_brightness_set;
  378. drvdata->backlight->cdev.brightness_get = k90_backlight_get;
  379. INIT_WORK(&drvdata->backlight->work, k90_backlight_work);
  380. ret = led_classdev_register(&dev->dev, &drvdata->backlight->cdev);
  381. if (ret != 0)
  382. goto fail_register_cdev;
  383. return 0;
  384. fail_register_cdev:
  385. kfree(drvdata->backlight->cdev.name);
  386. fail_name_alloc:
  387. kfree(drvdata->backlight);
  388. drvdata->backlight = NULL;
  389. fail_backlight_alloc:
  390. return ret;
  391. }
  392. static int k90_init_macro_functions(struct hid_device *dev)
  393. {
  394. int ret;
  395. struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
  396. struct k90_drvdata *k90;
  397. size_t name_sz;
  398. char *name;
  399. k90 = kzalloc(sizeof(struct k90_drvdata), GFP_KERNEL);
  400. if (!k90) {
  401. ret = -ENOMEM;
  402. goto fail_drvdata;
  403. }
  404. drvdata->k90 = k90;
  405. /* Init LED device for record LED */
  406. name_sz = strlen(dev_name(&dev->dev)) + sizeof(K90_RECORD_LED_SUFFIX);
  407. name = kzalloc(name_sz, GFP_KERNEL);
  408. if (!name) {
  409. ret = -ENOMEM;
  410. goto fail_record_led_alloc;
  411. }
  412. snprintf(name, name_sz, "%s" K90_RECORD_LED_SUFFIX,
  413. dev_name(&dev->dev));
  414. k90->record_led.removed = false;
  415. k90->record_led.cdev.name = name;
  416. k90->record_led.cdev.max_brightness = 1;
  417. k90->record_led.cdev.brightness_set = k90_brightness_set;
  418. k90->record_led.cdev.brightness_get = k90_record_led_get;
  419. INIT_WORK(&k90->record_led.work, k90_record_led_work);
  420. k90->record_led.brightness = 0;
  421. ret = led_classdev_register(&dev->dev, &k90->record_led.cdev);
  422. if (ret != 0)
  423. goto fail_record_led;
  424. /* Init attributes */
  425. ret = sysfs_create_group(&dev->dev.kobj, &k90_attr_group);
  426. if (ret != 0)
  427. goto fail_sysfs;
  428. return 0;
  429. fail_sysfs:
  430. k90->record_led.removed = true;
  431. led_classdev_unregister(&k90->record_led.cdev);
  432. cancel_work_sync(&k90->record_led.work);
  433. fail_record_led:
  434. kfree(k90->record_led.cdev.name);
  435. fail_record_led_alloc:
  436. kfree(k90);
  437. fail_drvdata:
  438. drvdata->k90 = NULL;
  439. return ret;
  440. }
  441. static void k90_cleanup_backlight(struct hid_device *dev)
  442. {
  443. struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
  444. if (drvdata->backlight) {
  445. drvdata->backlight->removed = true;
  446. led_classdev_unregister(&drvdata->backlight->cdev);
  447. cancel_work_sync(&drvdata->backlight->work);
  448. kfree(drvdata->backlight->cdev.name);
  449. kfree(drvdata->backlight);
  450. }
  451. }
  452. static void k90_cleanup_macro_functions(struct hid_device *dev)
  453. {
  454. struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
  455. struct k90_drvdata *k90 = drvdata->k90;
  456. if (k90) {
  457. sysfs_remove_group(&dev->dev.kobj, &k90_attr_group);
  458. k90->record_led.removed = true;
  459. led_classdev_unregister(&k90->record_led.cdev);
  460. cancel_work_sync(&k90->record_led.work);
  461. kfree(k90->record_led.cdev.name);
  462. kfree(k90);
  463. }
  464. }
  465. static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id)
  466. {
  467. int ret;
  468. unsigned long quirks = id->driver_data;
  469. struct corsair_drvdata *drvdata;
  470. struct usb_interface *usbif = to_usb_interface(dev->dev.parent);
  471. drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata),
  472. GFP_KERNEL);
  473. if (drvdata == NULL)
  474. return -ENOMEM;
  475. drvdata->quirks = quirks;
  476. hid_set_drvdata(dev, drvdata);
  477. ret = hid_parse(dev);
  478. if (ret != 0) {
  479. hid_err(dev, "parse failed\n");
  480. return ret;
  481. }
  482. ret = hid_hw_start(dev, HID_CONNECT_DEFAULT);
  483. if (ret != 0) {
  484. hid_err(dev, "hw start failed\n");
  485. return ret;
  486. }
  487. if (usbif->cur_altsetting->desc.bInterfaceNumber == 0) {
  488. if (quirks & CORSAIR_USE_K90_MACRO) {
  489. ret = k90_init_macro_functions(dev);
  490. if (ret != 0)
  491. hid_warn(dev, "Failed to initialize K90 macro functions.\n");
  492. }
  493. if (quirks & CORSAIR_USE_K90_BACKLIGHT) {
  494. ret = k90_init_backlight(dev);
  495. if (ret != 0)
  496. hid_warn(dev, "Failed to initialize K90 backlight.\n");
  497. }
  498. }
  499. return 0;
  500. }
  501. static void corsair_remove(struct hid_device *dev)
  502. {
  503. k90_cleanup_macro_functions(dev);
  504. k90_cleanup_backlight(dev);
  505. hid_hw_stop(dev);
  506. }
  507. static int corsair_event(struct hid_device *dev, struct hid_field *field,
  508. struct hid_usage *usage, __s32 value)
  509. {
  510. struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
  511. if (!drvdata->k90)
  512. return 0;
  513. switch (usage->hid & HID_USAGE) {
  514. case CORSAIR_USAGE_MACRO_RECORD_START:
  515. drvdata->k90->record_led.brightness = 1;
  516. break;
  517. case CORSAIR_USAGE_MACRO_RECORD_STOP:
  518. drvdata->k90->record_led.brightness = 0;
  519. break;
  520. default:
  521. break;
  522. }
  523. return 0;
  524. }
  525. static int corsair_input_mapping(struct hid_device *dev,
  526. struct hid_input *input,
  527. struct hid_field *field,
  528. struct hid_usage *usage, unsigned long **bit,
  529. int *max)
  530. {
  531. int gkey;
  532. if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD)
  533. return 0;
  534. gkey = corsair_usage_to_gkey(usage->hid & HID_USAGE);
  535. if (gkey != 0) {
  536. hid_map_usage_clear(input, usage, bit, max, EV_KEY,
  537. corsair_gkey_map[gkey - 1]);
  538. return 1;
  539. }
  540. if ((usage->hid & HID_USAGE) >= CORSAIR_USAGE_SPECIAL_MIN &&
  541. (usage->hid & HID_USAGE) <= CORSAIR_USAGE_SPECIAL_MAX) {
  542. switch (usage->hid & HID_USAGE) {
  543. case CORSAIR_USAGE_MACRO_RECORD_START:
  544. hid_map_usage_clear(input, usage, bit, max, EV_KEY,
  545. corsair_record_keycodes[0]);
  546. return 1;
  547. case CORSAIR_USAGE_MACRO_RECORD_STOP:
  548. hid_map_usage_clear(input, usage, bit, max, EV_KEY,
  549. corsair_record_keycodes[1]);
  550. return 1;
  551. case CORSAIR_USAGE_M1:
  552. hid_map_usage_clear(input, usage, bit, max, EV_KEY,
  553. corsair_profile_keycodes[0]);
  554. return 1;
  555. case CORSAIR_USAGE_M2:
  556. hid_map_usage_clear(input, usage, bit, max, EV_KEY,
  557. corsair_profile_keycodes[1]);
  558. return 1;
  559. case CORSAIR_USAGE_M3:
  560. hid_map_usage_clear(input, usage, bit, max, EV_KEY,
  561. corsair_profile_keycodes[2]);
  562. return 1;
  563. default:
  564. return -1;
  565. }
  566. }
  567. return 0;
  568. }
  569. /*
  570. * The report descriptor of Corsair Scimitar RGB Pro gaming mouse is
  571. * non parseable as they define two consecutive Logical Minimum for
  572. * the Usage Page (Consumer) in rdescs bytes 75 and 77 being 77 0x16
  573. * that should be obviousy 0x26 for Logical Magimum of 16 bits. This
  574. * prevents poper parsing of the report descriptor due Logical
  575. * Minimum being larger than Logical Maximum.
  576. *
  577. * This driver fixes the report descriptor for:
  578. * - USB ID b1c:1b3e, sold as Scimitar RGB Pro Gaming mouse
  579. */
  580. static __u8 *corsair_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
  581. unsigned int *rsize)
  582. {
  583. struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
  584. if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
  585. /*
  586. * Corsair Scimitar RGB Pro report descriptor is broken and
  587. * defines two different Logical Minimum for the Consumer
  588. * Application. The byte 77 should be a 0x26 defining a 16
  589. * bits integer for the Logical Maximum but it is a 0x16
  590. * instead (Logical Minimum)
  591. */
  592. switch (hdev->product) {
  593. case USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB:
  594. if (*rsize >= 172 && rdesc[75] == 0x15 && rdesc[77] == 0x16
  595. && rdesc[78] == 0xff && rdesc[79] == 0x0f) {
  596. hid_info(hdev, "Fixing up report descriptor\n");
  597. rdesc[77] = 0x26;
  598. }
  599. break;
  600. }
  601. }
  602. return rdesc;
  603. }
  604. static const struct hid_device_id corsair_devices[] = {
  605. { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90),
  606. .driver_data = CORSAIR_USE_K90_MACRO |
  607. CORSAIR_USE_K90_BACKLIGHT },
  608. { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,
  609. USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
  610. {}
  611. };
  612. MODULE_DEVICE_TABLE(hid, corsair_devices);
  613. static struct hid_driver corsair_driver = {
  614. .name = "corsair",
  615. .id_table = corsair_devices,
  616. .probe = corsair_probe,
  617. .event = corsair_event,
  618. .remove = corsair_remove,
  619. .input_mapping = corsair_input_mapping,
  620. .report_fixup = corsair_mouse_report_fixup,
  621. };
  622. module_hid_driver(corsair_driver);
  623. MODULE_LICENSE("GPL");
  624. /* Original K90 driver author */
  625. MODULE_AUTHOR("Clement Vuchener");
  626. /* Scimitar PRO RGB driver author */
  627. MODULE_AUTHOR("Oscar Campos");
  628. MODULE_DESCRIPTION("HID driver for Corsair devices");