22
22
enum lg_g15_model {
23
23
LG_G15 ,
24
24
LG_G15_V2 ,
25
+ LG_G510 ,
26
+ LG_G510_USB_AUDIO ,
25
27
};
26
28
27
29
enum lg_g15_led_type {
@@ -51,12 +53,16 @@ struct lg_g15_data {
51
53
struct hid_device * hdev ;
52
54
enum lg_g15_model model ;
53
55
struct lg_g15_led leds [LG_G15_LED_MAX ];
56
+ bool game_mode_enabled ;
54
57
};
55
58
56
59
static int lg_g15_update_led_brightness (struct lg_g15_data * g15 )
57
60
{
58
61
int ret ;
59
62
63
+ if (g15 -> model == LG_G510 || g15 -> model == LG_G510_USB_AUDIO )
64
+ return 0 ;
65
+
60
66
ret = hid_hw_raw_request (g15 -> hdev , LG_G15_FEATURE_REPORT ,
61
67
g15 -> transfer_buf , 4 ,
62
68
HID_FEATURE_REPORT , HID_REQ_GET_REPORT );
@@ -256,16 +262,73 @@ static int lg_g15_v2_event(struct lg_g15_data *g15, u8 *data, int size)
256
262
return 0 ;
257
263
}
258
264
265
+ static int lg_g510_event (struct lg_g15_data * g15 , u8 * data , int size )
266
+ {
267
+ bool game_mode_enabled ;
268
+ int i , val ;
269
+
270
+ /* G1 - G18 */
271
+ for (i = 0 ; i < 18 ; i ++ ) {
272
+ val = data [i / 8 + 1 ] & (1 << (i % 8 ));
273
+ input_report_key (g15 -> input , KEY_MACRO1 + i , val );
274
+ }
275
+
276
+ /* Game mode on/off slider */
277
+ game_mode_enabled = data [3 ] & 0x04 ;
278
+ if (game_mode_enabled != g15 -> game_mode_enabled ) {
279
+ if (game_mode_enabled )
280
+ hid_info (g15 -> hdev , "Game Mode enabled, Windows (super) key is disabled\n" );
281
+ else
282
+ hid_info (g15 -> hdev , "Game Mode disabled\n" );
283
+ g15 -> game_mode_enabled = game_mode_enabled ;
284
+ }
285
+
286
+ /* M1 - M3 */
287
+ for (i = 0 ; i < 3 ; i ++ ) {
288
+ val = data [3 ] & (0x10 << i );
289
+ input_report_key (g15 -> input , KEY_MACRO_PRESET1 + i , val );
290
+ }
291
+ /* MR */
292
+ input_report_key (g15 -> input , KEY_MACRO_RECORD_START , data [3 ] & 0x80 );
293
+
294
+ /* LCD menu keys */
295
+ for (i = 0 ; i < 5 ; i ++ ) {
296
+ val = data [4 ] & (1 << i );
297
+ input_report_key (g15 -> input , KEY_KBD_LCD_MENU1 + i , val );
298
+ }
299
+
300
+ /* Headphone Mute */
301
+ input_report_key (g15 -> input , KEY_MUTE , data [4 ] & 0x20 );
302
+ /* Microphone Mute */
303
+ input_report_key (g15 -> input , KEY_F20 , data [4 ] & 0x40 );
304
+
305
+ input_sync (g15 -> input );
306
+ return 0 ;
307
+ }
308
+
259
309
static int lg_g15_raw_event (struct hid_device * hdev , struct hid_report * report ,
260
310
u8 * data , int size )
261
311
{
262
312
struct lg_g15_data * g15 = hid_get_drvdata (hdev );
263
313
264
- if (g15 -> model == LG_G15 && data [ 0 ] == 0x02 && size == 9 )
265
- return lg_g15_event ( g15 , data , size ) ;
314
+ if (! g15 )
315
+ return 0 ;
266
316
267
- if (g15 -> model == LG_G15_V2 && data [0 ] == 0x02 && size == 5 )
268
- return lg_g15_v2_event (g15 , data , size );
317
+ switch (g15 -> model ) {
318
+ case LG_G15 :
319
+ if (data [0 ] == 0x02 && size == 9 )
320
+ return lg_g15_event (g15 , data , size );
321
+ break ;
322
+ case LG_G15_V2 :
323
+ if (data [0 ] == 0x02 && size == 5 )
324
+ return lg_g15_v2_event (g15 , data , size );
325
+ break ;
326
+ case LG_G510 :
327
+ case LG_G510_USB_AUDIO :
328
+ if (data [0 ] == 0x03 && size == 5 )
329
+ return lg_g510_event (g15 , data , size );
330
+ break ;
331
+ }
269
332
270
333
return 0 ;
271
334
}
@@ -312,15 +375,33 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i)
312
375
static int lg_g15_probe (struct hid_device * hdev , const struct hid_device_id * id )
313
376
{
314
377
u8 gkeys_settings_output_report = 0 ;
378
+ u8 gkeys_settings_feature_report = 0 ;
379
+ struct hid_report_enum * rep_enum ;
315
380
unsigned int connect_mask = 0 ;
381
+ bool has_ff000000 = false;
316
382
struct lg_g15_data * g15 ;
317
383
struct input_dev * input ;
384
+ struct hid_report * rep ;
318
385
int ret , i , gkeys = 0 ;
319
386
387
+ hdev -> quirks |= HID_QUIRK_INPUT_PER_APP ;
388
+
320
389
ret = hid_parse (hdev );
321
390
if (ret )
322
391
return ret ;
323
392
393
+ /*
394
+ * Some models have multiple interfaces, we want the interface with
395
+ * with the f000.0000 application input report.
396
+ */
397
+ rep_enum = & hdev -> report_enum [HID_INPUT_REPORT ];
398
+ list_for_each_entry (rep , & rep_enum -> report_list , list ) {
399
+ if (rep -> application == 0xff000000 )
400
+ has_ff000000 = true;
401
+ }
402
+ if (!has_ff000000 )
403
+ return hid_hw_start (hdev , HID_CONNECT_DEFAULT );
404
+
324
405
g15 = devm_kzalloc (& hdev -> dev , sizeof (* g15 ), GFP_KERNEL );
325
406
if (!g15 )
326
407
return - ENOMEM ;
@@ -353,6 +434,12 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
353
434
gkeys_settings_output_report = 0x02 ;
354
435
gkeys = 6 ;
355
436
break ;
437
+ case LG_G510 :
438
+ case LG_G510_USB_AUDIO :
439
+ connect_mask = HID_CONNECT_HIDINPUT | HID_CONNECT_HIDRAW ;
440
+ gkeys_settings_feature_report = 0x01 ;
441
+ gkeys = 18 ;
442
+ break ;
356
443
}
357
444
358
445
ret = hid_hw_start (hdev , connect_mask );
@@ -374,6 +461,15 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
374
461
hid_hw_close (hdev );
375
462
}
376
463
464
+ if (gkeys_settings_feature_report ) {
465
+ g15 -> transfer_buf [0 ] = gkeys_settings_feature_report ;
466
+ memset (g15 -> transfer_buf + 1 , 0 , gkeys );
467
+ ret = hid_hw_raw_request (g15 -> hdev ,
468
+ gkeys_settings_feature_report ,
469
+ g15 -> transfer_buf , gkeys + 1 ,
470
+ HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
471
+ }
472
+
377
473
if (ret < 0 ) {
378
474
hid_err (hdev , "Error disabling keyboard emulation for the G-keys\n" );
379
475
goto error_hw_stop ;
@@ -409,13 +505,27 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
409
505
for (i = 0 ; i < 5 ; i ++ )
410
506
input_set_capability (input , EV_KEY , KEY_KBD_LCD_MENU1 + i );
411
507
508
+ /*
509
+ * On the G510 only report headphone and mic mute keys when *not* using
510
+ * the builtin USB audio device. When the builtin audio is used these
511
+ * keys directly toggle mute (and the LEDs) on/off.
512
+ */
513
+ if (g15 -> model == LG_G510 ) {
514
+ input_set_capability (input , EV_KEY , KEY_MUTE );
515
+ /* Userspace expects F20 for micmute */
516
+ input_set_capability (input , EV_KEY , KEY_F20 );
517
+ }
518
+
412
519
g15 -> input = input ;
413
520
input_set_drvdata (input , hdev );
414
521
415
522
ret = input_register_device (input );
416
523
if (ret )
417
524
goto error_hw_stop ;
418
525
526
+ if (g15 -> model == LG_G510 || g15 -> model == LG_G510_USB_AUDIO )
527
+ return 0 ;
528
+
419
529
/* Register LED devices */
420
530
for (i = 0 ; i < LG_G15_LED_MAX ; i ++ ) {
421
531
ret = lg_g15_register_led (g15 , i );
@@ -437,6 +547,14 @@ static const struct hid_device_id lg_g15_devices[] = {
437
547
{ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
438
548
USB_DEVICE_ID_LOGITECH_G15_V2_LCD ),
439
549
.driver_data = LG_G15_V2 },
550
+ /* G510 without a headset plugged in */
551
+ { HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
552
+ USB_DEVICE_ID_LOGITECH_G510 ),
553
+ .driver_data = LG_G510 },
554
+ /* G510 with headset plugged in / with extra USB audio interface */
555
+ { HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
556
+ USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO ),
557
+ .driver_data = LG_G510_USB_AUDIO },
440
558
{ }
441
559
};
442
560
MODULE_DEVICE_TABLE (hid , lg_g15_devices );
0 commit comments