hid-lg-g15.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * HID driver for gaming keys on Logitech gaming keyboards (such as the G15)
  4. *
  5. * Copyright (c) 2019 Hans de Goede <hdegoede@redhat.com>
  6. */
  7. #include <linux/device.h>
  8. #include <linux/hid.h>
  9. #include <linux/leds.h>
  10. #include <linux/module.h>
  11. #include <linux/random.h>
  12. #include <linux/sched.h>
  13. #include <linux/usb.h>
  14. #include <linux/wait.h>
  15. #include "hid-ids.h"
  16. #define LG_G15_TRANSFER_BUF_SIZE 20
  17. #define LG_G15_FEATURE_REPORT 0x02
  18. #define LG_G510_FEATURE_M_KEYS_LEDS 0x04
  19. #define LG_G510_FEATURE_BACKLIGHT_RGB 0x05
  20. #define LG_G510_FEATURE_POWER_ON_RGB 0x06
  21. enum lg_g15_model {
  22. LG_G15,
  23. LG_G15_V2,
  24. LG_G510,
  25. LG_G510_USB_AUDIO,
  26. LG_Z10,
  27. };
  28. enum lg_g15_led_type {
  29. LG_G15_KBD_BRIGHTNESS,
  30. LG_G15_LCD_BRIGHTNESS,
  31. LG_G15_BRIGHTNESS_MAX,
  32. LG_G15_MACRO_PRESET1 = 2,
  33. LG_G15_MACRO_PRESET2,
  34. LG_G15_MACRO_PRESET3,
  35. LG_G15_MACRO_RECORD,
  36. LG_G15_LED_MAX
  37. };
  38. struct lg_g15_led {
  39. struct led_classdev cdev;
  40. enum led_brightness brightness;
  41. enum lg_g15_led_type led;
  42. u8 red, green, blue;
  43. };
  44. struct lg_g15_data {
  45. /* Must be first for proper dma alignment */
  46. u8 transfer_buf[LG_G15_TRANSFER_BUF_SIZE];
  47. /* Protects the transfer_buf and led brightness */
  48. struct mutex mutex;
  49. struct work_struct work;
  50. struct input_dev *input;
  51. struct hid_device *hdev;
  52. enum lg_g15_model model;
  53. struct lg_g15_led leds[LG_G15_LED_MAX];
  54. bool game_mode_enabled;
  55. };
  56. /******** G15 and G15 v2 LED functions ********/
  57. static int lg_g15_update_led_brightness(struct lg_g15_data *g15)
  58. {
  59. int ret;
  60. ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT,
  61. g15->transfer_buf, 4,
  62. HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
  63. if (ret != 4) {
  64. hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
  65. return (ret < 0) ? ret : -EIO;
  66. }
  67. g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = g15->transfer_buf[1];
  68. g15->leds[LG_G15_LCD_BRIGHTNESS].brightness = g15->transfer_buf[2];
  69. g15->leds[LG_G15_MACRO_PRESET1].brightness =
  70. !(g15->transfer_buf[3] & 0x01);
  71. g15->leds[LG_G15_MACRO_PRESET2].brightness =
  72. !(g15->transfer_buf[3] & 0x02);
  73. g15->leds[LG_G15_MACRO_PRESET3].brightness =
  74. !(g15->transfer_buf[3] & 0x04);
  75. g15->leds[LG_G15_MACRO_RECORD].brightness =
  76. !(g15->transfer_buf[3] & 0x08);
  77. return 0;
  78. }
  79. static enum led_brightness lg_g15_led_get(struct led_classdev *led_cdev)
  80. {
  81. struct lg_g15_led *g15_led =
  82. container_of(led_cdev, struct lg_g15_led, cdev);
  83. struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
  84. enum led_brightness brightness;
  85. mutex_lock(&g15->mutex);
  86. lg_g15_update_led_brightness(g15);
  87. brightness = g15->leds[g15_led->led].brightness;
  88. mutex_unlock(&g15->mutex);
  89. return brightness;
  90. }
  91. static int lg_g15_led_set(struct led_classdev *led_cdev,
  92. enum led_brightness brightness)
  93. {
  94. struct lg_g15_led *g15_led =
  95. container_of(led_cdev, struct lg_g15_led, cdev);
  96. struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
  97. u8 val, mask = 0;
  98. int i, ret;
  99. /* Ignore LED off on unregister / keyboard unplug */
  100. if (led_cdev->flags & LED_UNREGISTERING)
  101. return 0;
  102. mutex_lock(&g15->mutex);
  103. g15->transfer_buf[0] = LG_G15_FEATURE_REPORT;
  104. g15->transfer_buf[3] = 0;
  105. if (g15_led->led < LG_G15_BRIGHTNESS_MAX) {
  106. g15->transfer_buf[1] = g15_led->led + 1;
  107. g15->transfer_buf[2] = brightness << (g15_led->led * 4);
  108. } else {
  109. for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; i++) {
  110. if (i == g15_led->led)
  111. val = brightness;
  112. else
  113. val = g15->leds[i].brightness;
  114. if (val)
  115. mask |= 1 << (i - LG_G15_MACRO_PRESET1);
  116. }
  117. g15->transfer_buf[1] = 0x04;
  118. g15->transfer_buf[2] = ~mask;
  119. }
  120. ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT,
  121. g15->transfer_buf, 4,
  122. HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
  123. if (ret == 4) {
  124. /* Success */
  125. g15_led->brightness = brightness;
  126. ret = 0;
  127. } else {
  128. hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
  129. ret = (ret < 0) ? ret : -EIO;
  130. }
  131. mutex_unlock(&g15->mutex);
  132. return ret;
  133. }
  134. static void lg_g15_leds_changed_work(struct work_struct *work)
  135. {
  136. struct lg_g15_data *g15 = container_of(work, struct lg_g15_data, work);
  137. enum led_brightness old_brightness[LG_G15_BRIGHTNESS_MAX];
  138. enum led_brightness brightness[LG_G15_BRIGHTNESS_MAX];
  139. int i, ret;
  140. mutex_lock(&g15->mutex);
  141. for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++)
  142. old_brightness[i] = g15->leds[i].brightness;
  143. ret = lg_g15_update_led_brightness(g15);
  144. for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++)
  145. brightness[i] = g15->leds[i].brightness;
  146. mutex_unlock(&g15->mutex);
  147. if (ret)
  148. return;
  149. for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++) {
  150. if (brightness[i] == old_brightness[i])
  151. continue;
  152. led_classdev_notify_brightness_hw_changed(&g15->leds[i].cdev,
  153. brightness[i]);
  154. }
  155. }
  156. /******** G510 LED functions ********/
  157. static int lg_g510_get_initial_led_brightness(struct lg_g15_data *g15, int i)
  158. {
  159. int ret, high;
  160. ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_BACKLIGHT_RGB + i,
  161. g15->transfer_buf, 4,
  162. HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
  163. if (ret != 4) {
  164. hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
  165. return (ret < 0) ? ret : -EIO;
  166. }
  167. high = max3(g15->transfer_buf[1], g15->transfer_buf[2],
  168. g15->transfer_buf[3]);
  169. if (high) {
  170. g15->leds[i].red =
  171. DIV_ROUND_CLOSEST(g15->transfer_buf[1] * 255, high);
  172. g15->leds[i].green =
  173. DIV_ROUND_CLOSEST(g15->transfer_buf[2] * 255, high);
  174. g15->leds[i].blue =
  175. DIV_ROUND_CLOSEST(g15->transfer_buf[3] * 255, high);
  176. g15->leds[i].brightness = high;
  177. } else {
  178. g15->leds[i].red = 255;
  179. g15->leds[i].green = 255;
  180. g15->leds[i].blue = 255;
  181. g15->leds[i].brightness = 0;
  182. }
  183. return 0;
  184. }
  185. /* Must be called with g15->mutex locked */
  186. static int lg_g510_kbd_led_write(struct lg_g15_data *g15,
  187. struct lg_g15_led *g15_led,
  188. enum led_brightness brightness)
  189. {
  190. int ret;
  191. g15->transfer_buf[0] = 5 + g15_led->led;
  192. g15->transfer_buf[1] =
  193. DIV_ROUND_CLOSEST(g15_led->red * brightness, 255);
  194. g15->transfer_buf[2] =
  195. DIV_ROUND_CLOSEST(g15_led->green * brightness, 255);
  196. g15->transfer_buf[3] =
  197. DIV_ROUND_CLOSEST(g15_led->blue * brightness, 255);
  198. ret = hid_hw_raw_request(g15->hdev,
  199. LG_G510_FEATURE_BACKLIGHT_RGB + g15_led->led,
  200. g15->transfer_buf, 4,
  201. HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
  202. if (ret == 4) {
  203. /* Success */
  204. g15_led->brightness = brightness;
  205. ret = 0;
  206. } else {
  207. hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
  208. ret = (ret < 0) ? ret : -EIO;
  209. }
  210. return ret;
  211. }
  212. static int lg_g510_kbd_led_set(struct led_classdev *led_cdev,
  213. enum led_brightness brightness)
  214. {
  215. struct lg_g15_led *g15_led =
  216. container_of(led_cdev, struct lg_g15_led, cdev);
  217. struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
  218. int ret;
  219. /* Ignore LED off on unregister / keyboard unplug */
  220. if (led_cdev->flags & LED_UNREGISTERING)
  221. return 0;
  222. mutex_lock(&g15->mutex);
  223. ret = lg_g510_kbd_led_write(g15, g15_led, brightness);
  224. mutex_unlock(&g15->mutex);
  225. return ret;
  226. }
  227. static enum led_brightness lg_g510_kbd_led_get(struct led_classdev *led_cdev)
  228. {
  229. struct lg_g15_led *g15_led =
  230. container_of(led_cdev, struct lg_g15_led, cdev);
  231. return g15_led->brightness;
  232. }
  233. static ssize_t color_store(struct device *dev, struct device_attribute *attr,
  234. const char *buf, size_t count)
  235. {
  236. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  237. struct lg_g15_led *g15_led =
  238. container_of(led_cdev, struct lg_g15_led, cdev);
  239. struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
  240. unsigned long value;
  241. int ret;
  242. if (count < 7 || (count == 8 && buf[7] != '\n') || count > 8)
  243. return -EINVAL;
  244. if (buf[0] != '#')
  245. return -EINVAL;
  246. ret = kstrtoul(buf + 1, 16, &value);
  247. if (ret)
  248. return ret;
  249. mutex_lock(&g15->mutex);
  250. g15_led->red = (value & 0xff0000) >> 16;
  251. g15_led->green = (value & 0x00ff00) >> 8;
  252. g15_led->blue = (value & 0x0000ff);
  253. ret = lg_g510_kbd_led_write(g15, g15_led, g15_led->brightness);
  254. mutex_unlock(&g15->mutex);
  255. return (ret < 0) ? ret : count;
  256. }
  257. static ssize_t color_show(struct device *dev, struct device_attribute *attr,
  258. char *buf)
  259. {
  260. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  261. struct lg_g15_led *g15_led =
  262. container_of(led_cdev, struct lg_g15_led, cdev);
  263. struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
  264. ssize_t ret;
  265. mutex_lock(&g15->mutex);
  266. ret = sprintf(buf, "#%02x%02x%02x\n",
  267. g15_led->red, g15_led->green, g15_led->blue);
  268. mutex_unlock(&g15->mutex);
  269. return ret;
  270. }
  271. static DEVICE_ATTR_RW(color);
  272. static struct attribute *lg_g510_kbd_led_attrs[] = {
  273. &dev_attr_color.attr,
  274. NULL,
  275. };
  276. static const struct attribute_group lg_g510_kbd_led_group = {
  277. .attrs = lg_g510_kbd_led_attrs,
  278. };
  279. static const struct attribute_group *lg_g510_kbd_led_groups[] = {
  280. &lg_g510_kbd_led_group,
  281. NULL,
  282. };
  283. static void lg_g510_leds_sync_work(struct work_struct *work)
  284. {
  285. struct lg_g15_data *g15 = container_of(work, struct lg_g15_data, work);
  286. mutex_lock(&g15->mutex);
  287. lg_g510_kbd_led_write(g15, &g15->leds[LG_G15_KBD_BRIGHTNESS],
  288. g15->leds[LG_G15_KBD_BRIGHTNESS].brightness);
  289. mutex_unlock(&g15->mutex);
  290. }
  291. static int lg_g510_update_mkey_led_brightness(struct lg_g15_data *g15)
  292. {
  293. int ret;
  294. ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS,
  295. g15->transfer_buf, 2,
  296. HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
  297. if (ret != 2) {
  298. hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
  299. ret = (ret < 0) ? ret : -EIO;
  300. }
  301. g15->leds[LG_G15_MACRO_PRESET1].brightness =
  302. !!(g15->transfer_buf[1] & 0x80);
  303. g15->leds[LG_G15_MACRO_PRESET2].brightness =
  304. !!(g15->transfer_buf[1] & 0x40);
  305. g15->leds[LG_G15_MACRO_PRESET3].brightness =
  306. !!(g15->transfer_buf[1] & 0x20);
  307. g15->leds[LG_G15_MACRO_RECORD].brightness =
  308. !!(g15->transfer_buf[1] & 0x10);
  309. return 0;
  310. }
  311. static enum led_brightness lg_g510_mkey_led_get(struct led_classdev *led_cdev)
  312. {
  313. struct lg_g15_led *g15_led =
  314. container_of(led_cdev, struct lg_g15_led, cdev);
  315. struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
  316. enum led_brightness brightness;
  317. mutex_lock(&g15->mutex);
  318. lg_g510_update_mkey_led_brightness(g15);
  319. brightness = g15->leds[g15_led->led].brightness;
  320. mutex_unlock(&g15->mutex);
  321. return brightness;
  322. }
  323. static int lg_g510_mkey_led_set(struct led_classdev *led_cdev,
  324. enum led_brightness brightness)
  325. {
  326. struct lg_g15_led *g15_led =
  327. container_of(led_cdev, struct lg_g15_led, cdev);
  328. struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
  329. u8 val, mask = 0;
  330. int i, ret;
  331. /* Ignore LED off on unregister / keyboard unplug */
  332. if (led_cdev->flags & LED_UNREGISTERING)
  333. return 0;
  334. mutex_lock(&g15->mutex);
  335. for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; i++) {
  336. if (i == g15_led->led)
  337. val = brightness;
  338. else
  339. val = g15->leds[i].brightness;
  340. if (val)
  341. mask |= 0x80 >> (i - LG_G15_MACRO_PRESET1);
  342. }
  343. g15->transfer_buf[0] = LG_G510_FEATURE_M_KEYS_LEDS;
  344. g15->transfer_buf[1] = mask;
  345. ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS,
  346. g15->transfer_buf, 2,
  347. HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
  348. if (ret == 2) {
  349. /* Success */
  350. g15_led->brightness = brightness;
  351. ret = 0;
  352. } else {
  353. hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
  354. ret = (ret < 0) ? ret : -EIO;
  355. }
  356. mutex_unlock(&g15->mutex);
  357. return ret;
  358. }
  359. /******** Generic LED functions ********/
  360. static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
  361. {
  362. int ret;
  363. switch (g15->model) {
  364. case LG_G15:
  365. case LG_G15_V2:
  366. return lg_g15_update_led_brightness(g15);
  367. case LG_G510:
  368. case LG_G510_USB_AUDIO:
  369. ret = lg_g510_get_initial_led_brightness(g15, 0);
  370. if (ret)
  371. return ret;
  372. ret = lg_g510_get_initial_led_brightness(g15, 1);
  373. if (ret)
  374. return ret;
  375. return lg_g510_update_mkey_led_brightness(g15);
  376. case LG_Z10:
  377. /*
  378. * Getting the LCD backlight brightness is not supported.
  379. * Reading Feature(2) fails with -EPIPE and this crashes
  380. * the LCD and touch keys part of the speakers.
  381. */
  382. return 0;
  383. }
  384. return -EINVAL; /* Never reached */
  385. }
  386. /******** Input functions ********/
  387. /* On the G15 Mark I Logitech has been quite creative with which bit is what */
  388. static void lg_g15_handle_lcd_menu_keys(struct lg_g15_data *g15, u8 *data)
  389. {
  390. int i, val;
  391. /* Most left (round/display) button below the LCD */
  392. input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[8] & 0x80);
  393. /* 4 other buttons below the LCD */
  394. for (i = 0; i < 4; i++) {
  395. val = data[i + 2] & 0x80;
  396. input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val);
  397. }
  398. }
  399. static int lg_g15_event(struct lg_g15_data *g15, u8 *data)
  400. {
  401. int i, val;
  402. /* G1 - G6 */
  403. for (i = 0; i < 6; i++) {
  404. val = data[i + 1] & (1 << i);
  405. input_report_key(g15->input, KEY_MACRO1 + i, val);
  406. }
  407. /* G7 - G12 */
  408. for (i = 0; i < 6; i++) {
  409. val = data[i + 2] & (1 << i);
  410. input_report_key(g15->input, KEY_MACRO7 + i, val);
  411. }
  412. /* G13 - G17 */
  413. for (i = 0; i < 5; i++) {
  414. val = data[i + 1] & (4 << i);
  415. input_report_key(g15->input, KEY_MACRO13 + i, val);
  416. }
  417. /* G18 */
  418. input_report_key(g15->input, KEY_MACRO18, data[8] & 0x40);
  419. /* M1 - M3 */
  420. for (i = 0; i < 3; i++) {
  421. val = data[i + 6] & (1 << i);
  422. input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val);
  423. }
  424. /* MR */
  425. input_report_key(g15->input, KEY_MACRO_RECORD_START, data[7] & 0x40);
  426. lg_g15_handle_lcd_menu_keys(g15, data);
  427. /* Backlight cycle button pressed? */
  428. if (data[1] & 0x80)
  429. schedule_work(&g15->work);
  430. input_sync(g15->input);
  431. return 0;
  432. }
  433. static int lg_g15_v2_event(struct lg_g15_data *g15, u8 *data)
  434. {
  435. int i, val;
  436. /* G1 - G6 */
  437. for (i = 0; i < 6; i++) {
  438. val = data[1] & (1 << i);
  439. input_report_key(g15->input, KEY_MACRO1 + i, val);
  440. }
  441. /* M1 - M3 + MR */
  442. input_report_key(g15->input, KEY_MACRO_PRESET1, data[1] & 0x40);
  443. input_report_key(g15->input, KEY_MACRO_PRESET2, data[1] & 0x80);
  444. input_report_key(g15->input, KEY_MACRO_PRESET3, data[2] & 0x20);
  445. input_report_key(g15->input, KEY_MACRO_RECORD_START, data[2] & 0x40);
  446. /* Round button to the left of the LCD */
  447. input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[2] & 0x80);
  448. /* 4 buttons below the LCD */
  449. for (i = 0; i < 4; i++) {
  450. val = data[2] & (2 << i);
  451. input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val);
  452. }
  453. /* Backlight cycle button pressed? */
  454. if (data[2] & 0x01)
  455. schedule_work(&g15->work);
  456. input_sync(g15->input);
  457. return 0;
  458. }
  459. static int lg_g510_event(struct lg_g15_data *g15, u8 *data)
  460. {
  461. bool game_mode_enabled;
  462. int i, val;
  463. /* G1 - G18 */
  464. for (i = 0; i < 18; i++) {
  465. val = data[i / 8 + 1] & (1 << (i % 8));
  466. input_report_key(g15->input, KEY_MACRO1 + i, val);
  467. }
  468. /* Game mode on/off slider */
  469. game_mode_enabled = data[3] & 0x04;
  470. if (game_mode_enabled != g15->game_mode_enabled) {
  471. if (game_mode_enabled)
  472. hid_info(g15->hdev, "Game Mode enabled, Windows (super) key is disabled\n");
  473. else
  474. hid_info(g15->hdev, "Game Mode disabled\n");
  475. g15->game_mode_enabled = game_mode_enabled;
  476. }
  477. /* M1 - M3 */
  478. for (i = 0; i < 3; i++) {
  479. val = data[3] & (0x10 << i);
  480. input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val);
  481. }
  482. /* MR */
  483. input_report_key(g15->input, KEY_MACRO_RECORD_START, data[3] & 0x80);
  484. /* LCD menu keys */
  485. for (i = 0; i < 5; i++) {
  486. val = data[4] & (1 << i);
  487. input_report_key(g15->input, KEY_KBD_LCD_MENU1 + i, val);
  488. }
  489. /* Headphone Mute */
  490. input_report_key(g15->input, KEY_MUTE, data[4] & 0x20);
  491. /* Microphone Mute */
  492. input_report_key(g15->input, KEY_F20, data[4] & 0x40);
  493. input_sync(g15->input);
  494. return 0;
  495. }
  496. static int lg_g510_leds_event(struct lg_g15_data *g15, u8 *data)
  497. {
  498. bool backlight_disabled;
  499. /*
  500. * The G510 ignores backlight updates when the backlight is turned off
  501. * through the light toggle button on the keyboard, to work around this
  502. * we queue a workitem to sync values when the backlight is turned on.
  503. */
  504. backlight_disabled = data[1] & 0x04;
  505. if (!backlight_disabled)
  506. schedule_work(&g15->work);
  507. return 0;
  508. }
  509. static int lg_g15_raw_event(struct hid_device *hdev, struct hid_report *report,
  510. u8 *data, int size)
  511. {
  512. struct lg_g15_data *g15 = hid_get_drvdata(hdev);
  513. if (!g15)
  514. return 0;
  515. switch (g15->model) {
  516. case LG_G15:
  517. if (data[0] == 0x02 && size == 9)
  518. return lg_g15_event(g15, data);
  519. break;
  520. case LG_G15_V2:
  521. if (data[0] == 0x02 && size == 5)
  522. return lg_g15_v2_event(g15, data);
  523. break;
  524. case LG_Z10:
  525. if (data[0] == 0x02 && size == 9) {
  526. lg_g15_handle_lcd_menu_keys(g15, data);
  527. input_sync(g15->input);
  528. }
  529. break;
  530. case LG_G510:
  531. case LG_G510_USB_AUDIO:
  532. if (data[0] == 0x03 && size == 5)
  533. return lg_g510_event(g15, data);
  534. if (data[0] == 0x04 && size == 2)
  535. return lg_g510_leds_event(g15, data);
  536. break;
  537. }
  538. return 0;
  539. }
  540. static int lg_g15_input_open(struct input_dev *dev)
  541. {
  542. struct hid_device *hdev = input_get_drvdata(dev);
  543. return hid_hw_open(hdev);
  544. }
  545. static void lg_g15_input_close(struct input_dev *dev)
  546. {
  547. struct hid_device *hdev = input_get_drvdata(dev);
  548. hid_hw_close(hdev);
  549. }
  550. static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
  551. {
  552. g15->leds[i].led = i;
  553. g15->leds[i].cdev.name = name;
  554. switch (g15->model) {
  555. case LG_G15:
  556. case LG_G15_V2:
  557. g15->leds[i].cdev.brightness_get = lg_g15_led_get;
  558. fallthrough;
  559. case LG_Z10:
  560. g15->leds[i].cdev.brightness_set_blocking = lg_g15_led_set;
  561. if (i < LG_G15_BRIGHTNESS_MAX) {
  562. g15->leds[i].cdev.flags = LED_BRIGHT_HW_CHANGED;
  563. g15->leds[i].cdev.max_brightness = 2;
  564. } else {
  565. g15->leds[i].cdev.max_brightness = 1;
  566. }
  567. break;
  568. case LG_G510:
  569. case LG_G510_USB_AUDIO:
  570. switch (i) {
  571. case LG_G15_LCD_BRIGHTNESS:
  572. /*
  573. * The G510 does not have a separate LCD brightness,
  574. * but it does have a separate power-on (reset) value.
  575. */
  576. g15->leds[i].cdev.name = "g15::power_on_backlight_val";
  577. fallthrough;
  578. case LG_G15_KBD_BRIGHTNESS:
  579. g15->leds[i].cdev.brightness_set_blocking =
  580. lg_g510_kbd_led_set;
  581. g15->leds[i].cdev.brightness_get =
  582. lg_g510_kbd_led_get;
  583. g15->leds[i].cdev.max_brightness = 255;
  584. g15->leds[i].cdev.groups = lg_g510_kbd_led_groups;
  585. break;
  586. default:
  587. g15->leds[i].cdev.brightness_set_blocking =
  588. lg_g510_mkey_led_set;
  589. g15->leds[i].cdev.brightness_get =
  590. lg_g510_mkey_led_get;
  591. g15->leds[i].cdev.max_brightness = 1;
  592. }
  593. break;
  594. }
  595. return devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev);
  596. }
  597. /* Common input device init code shared between keyboards and Z-10 speaker handling */
  598. static void lg_g15_init_input_dev(struct hid_device *hdev, struct input_dev *input,
  599. const char *name)
  600. {
  601. int i;
  602. input->name = name;
  603. input->phys = hdev->phys;
  604. input->uniq = hdev->uniq;
  605. input->id.bustype = hdev->bus;
  606. input->id.vendor = hdev->vendor;
  607. input->id.product = hdev->product;
  608. input->id.version = hdev->version;
  609. input->dev.parent = &hdev->dev;
  610. input->open = lg_g15_input_open;
  611. input->close = lg_g15_input_close;
  612. /* Keys below the LCD, intended for controlling a menu on the LCD */
  613. for (i = 0; i < 5; i++)
  614. input_set_capability(input, EV_KEY, KEY_KBD_LCD_MENU1 + i);
  615. }
  616. static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
  617. {
  618. static const char * const led_names[] = {
  619. "g15::kbd_backlight",
  620. "g15::lcd_backlight",
  621. "g15::macro_preset1",
  622. "g15::macro_preset2",
  623. "g15::macro_preset3",
  624. "g15::macro_record",
  625. };
  626. u8 gkeys_settings_output_report = 0;
  627. u8 gkeys_settings_feature_report = 0;
  628. struct hid_report_enum *rep_enum;
  629. unsigned int connect_mask = 0;
  630. bool has_ff000000 = false;
  631. struct lg_g15_data *g15;
  632. struct input_dev *input;
  633. struct hid_report *rep;
  634. int ret, i, gkeys = 0;
  635. hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
  636. ret = hid_parse(hdev);
  637. if (ret)
  638. return ret;
  639. /*
  640. * Some models have multiple interfaces, we want the interface with
  641. * the f000.0000 application input report.
  642. */
  643. rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
  644. list_for_each_entry(rep, &rep_enum->report_list, list) {
  645. if (rep->application == 0xff000000)
  646. has_ff000000 = true;
  647. }
  648. if (!has_ff000000)
  649. return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
  650. g15 = devm_kzalloc(&hdev->dev, sizeof(*g15), GFP_KERNEL);
  651. if (!g15)
  652. return -ENOMEM;
  653. mutex_init(&g15->mutex);
  654. input = devm_input_allocate_device(&hdev->dev);
  655. if (!input)
  656. return -ENOMEM;
  657. g15->hdev = hdev;
  658. g15->model = id->driver_data;
  659. g15->input = input;
  660. input_set_drvdata(input, hdev);
  661. hid_set_drvdata(hdev, (void *)g15);
  662. switch (g15->model) {
  663. case LG_G15:
  664. INIT_WORK(&g15->work, lg_g15_leds_changed_work);
  665. /*
  666. * The G15 and G15 v2 use a separate usb-device (on a builtin
  667. * hub) which emulates a keyboard for the F1 - F12 emulation
  668. * on the G-keys, which we disable, rendering the emulated kbd
  669. * non-functional, so we do not let hid-input connect.
  670. */
  671. connect_mask = HID_CONNECT_HIDRAW;
  672. gkeys_settings_output_report = 0x02;
  673. gkeys = 18;
  674. break;
  675. case LG_G15_V2:
  676. INIT_WORK(&g15->work, lg_g15_leds_changed_work);
  677. connect_mask = HID_CONNECT_HIDRAW;
  678. gkeys_settings_output_report = 0x02;
  679. gkeys = 6;
  680. break;
  681. case LG_G510:
  682. case LG_G510_USB_AUDIO:
  683. INIT_WORK(&g15->work, lg_g510_leds_sync_work);
  684. connect_mask = HID_CONNECT_HIDINPUT | HID_CONNECT_HIDRAW;
  685. gkeys_settings_feature_report = 0x01;
  686. gkeys = 18;
  687. break;
  688. case LG_Z10:
  689. connect_mask = HID_CONNECT_HIDRAW;
  690. break;
  691. }
  692. ret = hid_hw_start(hdev, connect_mask);
  693. if (ret)
  694. return ret;
  695. /* Tell the keyboard to stop sending F1-F12 + 1-6 for G1 - G18 */
  696. if (gkeys_settings_output_report) {
  697. g15->transfer_buf[0] = gkeys_settings_output_report;
  698. memset(g15->transfer_buf + 1, 0, gkeys);
  699. /*
  700. * The kbd ignores our output report if we do not queue
  701. * an URB on the USB input endpoint first...
  702. */
  703. ret = hid_hw_open(hdev);
  704. if (ret)
  705. goto error_hw_stop;
  706. ret = hid_hw_output_report(hdev, g15->transfer_buf, gkeys + 1);
  707. hid_hw_close(hdev);
  708. }
  709. if (gkeys_settings_feature_report) {
  710. g15->transfer_buf[0] = gkeys_settings_feature_report;
  711. memset(g15->transfer_buf + 1, 0, gkeys);
  712. ret = hid_hw_raw_request(g15->hdev,
  713. gkeys_settings_feature_report,
  714. g15->transfer_buf, gkeys + 1,
  715. HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
  716. }
  717. if (ret < 0) {
  718. hid_err(hdev, "Error %d disabling keyboard emulation for the G-keys, falling back to generic hid-input driver\n",
  719. ret);
  720. hid_set_drvdata(hdev, NULL);
  721. return 0;
  722. }
  723. /* Get initial brightness levels */
  724. ret = lg_g15_get_initial_led_brightness(g15);
  725. if (ret)
  726. goto error_hw_stop;
  727. if (g15->model == LG_Z10) {
  728. lg_g15_init_input_dev(hdev, g15->input, "Logitech Z-10 LCD Menu Keys");
  729. ret = input_register_device(g15->input);
  730. if (ret)
  731. goto error_hw_stop;
  732. ret = lg_g15_register_led(g15, 1, "z-10::lcd_backlight");
  733. if (ret)
  734. goto error_hw_stop;
  735. return 0; /* All done */
  736. }
  737. /* Setup and register input device */
  738. lg_g15_init_input_dev(hdev, input, "Logitech Gaming Keyboard Gaming Keys");
  739. /* G-keys */
  740. for (i = 0; i < gkeys; i++)
  741. input_set_capability(input, EV_KEY, KEY_MACRO1 + i);
  742. /* M1 - M3 and MR keys */
  743. for (i = 0; i < 3; i++)
  744. input_set_capability(input, EV_KEY, KEY_MACRO_PRESET1 + i);
  745. input_set_capability(input, EV_KEY, KEY_MACRO_RECORD_START);
  746. /*
  747. * On the G510 only report headphone and mic mute keys when *not* using
  748. * the builtin USB audio device. When the builtin audio is used these
  749. * keys directly toggle mute (and the LEDs) on/off.
  750. */
  751. if (g15->model == LG_G510) {
  752. input_set_capability(input, EV_KEY, KEY_MUTE);
  753. /* Userspace expects F20 for micmute */
  754. input_set_capability(input, EV_KEY, KEY_F20);
  755. }
  756. ret = input_register_device(input);
  757. if (ret)
  758. goto error_hw_stop;
  759. /* Register LED devices */
  760. for (i = 0; i < LG_G15_LED_MAX; i++) {
  761. ret = lg_g15_register_led(g15, i, led_names[i]);
  762. if (ret)
  763. goto error_hw_stop;
  764. }
  765. return 0;
  766. error_hw_stop:
  767. hid_hw_stop(hdev);
  768. return ret;
  769. }
  770. static const struct hid_device_id lg_g15_devices[] = {
  771. /* The G11 is a G15 without the LCD, treat it as a G15 */
  772. { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
  773. USB_DEVICE_ID_LOGITECH_G11),
  774. .driver_data = LG_G15 },
  775. { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
  776. USB_DEVICE_ID_LOGITECH_G15_LCD),
  777. .driver_data = LG_G15 },
  778. { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
  779. USB_DEVICE_ID_LOGITECH_G15_V2_LCD),
  780. .driver_data = LG_G15_V2 },
  781. /* G510 without a headset plugged in */
  782. { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
  783. USB_DEVICE_ID_LOGITECH_G510),
  784. .driver_data = LG_G510 },
  785. /* G510 with headset plugged in / with extra USB audio interface */
  786. { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
  787. USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO),
  788. .driver_data = LG_G510_USB_AUDIO },
  789. /* Z-10 speakers */
  790. { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
  791. USB_DEVICE_ID_LOGITECH_Z_10_SPK),
  792. .driver_data = LG_Z10 },
  793. { }
  794. };
  795. MODULE_DEVICE_TABLE(hid, lg_g15_devices);
  796. static struct hid_driver lg_g15_driver = {
  797. .name = "lg-g15",
  798. .id_table = lg_g15_devices,
  799. .raw_event = lg_g15_raw_event,
  800. .probe = lg_g15_probe,
  801. };
  802. module_hid_driver(lg_g15_driver);
  803. MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
  804. MODULE_DESCRIPTION("HID driver for gaming keys on Logitech gaming keyboards");
  805. MODULE_LICENSE("GPL");