hid-lg-g15.c 24 KB

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